Quelle est la différence entre le module.exports de Node et l'export default de ES6 ? J'essaie de comprendre pourquoi j'obtiens l'erreur "__ is not a constructor" ; lorsque j'essaie d'exporter default` dans 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
Le problème est le suivant
Au moment où nous écrivons ces lignes, aucun environnement ne supporte nativement les modules ES6. Lorsque vous les utilisez dans Node.js, vous devez utiliser quelque chose comme Babel pour convertir les modules en CommonJS. Mais comment cela se passe-t-il exactement ?
Beaucoup de gens considèrent que "module.exports = ..." est équivalent à "exporter default ...
et que "exporter.foo ..." est équivalent à "exporter const foo = ...
". Ce n'est pourtant pas tout à fait vrai, ou du moins pas de la manière dont Babel le fait.
Les exportations "par défaut" de ES6 sont en fait aussi des exportations "nommées", sauf que "par défaut" est un nom "réservé" et qu'il existe un support syntaxique spécial pour ce nom. Voyons comment Babel compile les exportations nommées et par défaut :
// 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;
Ici, nous pouvons voir que l'exportation par défaut devient une propriété de l'objet exports
, tout comme foo
.
Nous pouvons importer le module de deux façons : Soit en utilisant CommonJS, soit en utilisant la syntaxe import
de ES6.
Votre problème: Je crois que vous faites quelque chose comme :
var bar = require('./input');
new bar();
en vous attendant à ce que bar
se voit attribuer la valeur de l'exportation par défaut. Mais comme nous pouvons le voir dans l'exemple ci-dessus, l'exportation par défaut est assignée à la propriété default
!
Donc pour accéder à l'exportation par défaut, nous devons en fait faire
var bar = require('./input').default;
Si nous utilisons la syntaxe de module ES6, à savoir
import bar from './input';
console.log(bar);
Babel la transformera en
'use strict';
var _input = require('./input');
var _input2 = _interopRequireDefault(_input);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
console.log(_input2.default);
Vous pouvez voir que chaque accès à bar
est converti en accès .default
.
Pour l'instant, pour que cela fonctionne, le fichier qui requiert ou importe SlimShady
doit être compilé en utilisant Babel avec 'use strict'
.
J'utilise babel-cli
6.18.0 dans le projet où j'ai initialement rencontré cette erreur.
'use strict'
, c'est une mauvaise nouvelle pour les ours.var 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