Was ist der Unterschied zwischen Node's module.exports
und ES6's export default
? Ich versuche herauszufinden, warum ich den Fehler "__ ist kein Konstruktor" bekomme, wenn ich versuche, export default
in Node.js 6.2.2.
'use strict'
class SlimShady {
constructor(options) {
this._options = options
}
sayName() {
return 'My name is Slim Shady.'
}
}
// This works
module.exports = SlimShady
'use strict'
class SlimShady {
constructor(options) {
this._options = options
}
sayName() {
return 'My name is Slim Shady.'
}
}
// This will cause the "SlimShady is not a constructor" error
// if in another file I try `let marshall = new SlimShady()`
export default SlimShady
Das Problem liegt bei
Zum Zeitpunkt der Erstellung dieses Artikels unterstützt keine Umgebung ES6-Module von Haus aus. Wenn Sie sie in Node.js verwenden, müssen Sie etwas wie Babel verwenden, um die Module in CommonJS zu konvertieren. Aber wie genau geschieht das?
Viele Leute halten module.exports = ...
für gleichwertig mit export default ...
und exports.foo ...
für gleichwertig mit export const foo = ...
. Das ist aber nicht ganz richtig, oder zumindest nicht so, wie Babel es macht.
ES6 default
Exporte sind eigentlich auch benannte Exporte, außer dass default
ein "reservierter" Name ist und es gibt eine spezielle Syntaxunterstützung für ihn. Schauen wir uns an, wie Babel benannte und Standard-Exporte kompiliert:
// input
export const foo = 42;
export default 21;
// output
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var foo = exports.foo = 42;
exports.default = 21;
Hier können wir sehen, dass der Standardexport eine Eigenschaft des Objekts "exports" wird, genau wie "foo".
Wir können das Modul auf zwei Arten importieren: Entweder mit CommonJS oder mit der ES6-Syntax import
.
Ihr Problem: Ich glaube, Sie tun etwas wie:
var bar = require('./input');
new bar();
in der Erwartung, dass "bar" der Wert des Standardexports zugewiesen wird. Aber wie wir im obigen Beispiel sehen können, wird der Standardexport der Eigenschaft default
zugewiesen!
Um auf den Standardexport zuzugreifen, müssen wir also tatsächlich Folgendes tun
var bar = require('./input').default;
Wenn wir die ES6-Modul-Syntax verwenden, nämlich
import bar from './input';
console.log(bar);
Babel wandelt es um in
'use strict';
var _input = require('./input');
var _input2 = _interopRequireDefault(_input);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
console.log(_input2.default);
Sie können sehen, dass jeder Zugriff auf bar
in einen Zugriff auf .default
umgewandelt wird.
tl;dr damit dies funktioniert, muss die Datei, die SlimShady
benötigt oder importiert, mit Babel mit 'use strict'
kompiliert werden.
Ich verwende babel-cli
6.18.0 in dem Projekt, in dem ich ursprünglich auf diesen Fehler gestoßen bin.
'use strict'
ist Bad News Bearsvar SlimShady = require('./slim-shady');
var marshall = new SlimShady(); // uh, oh...
'use strict'
import SlimShady from './slim-shady'
var marshall = new SlimShady() // all good in the hood