Qual è la differenza tra il module.exports
di Node e il export default
di ES6? Sto cercando di capire perché ottengo il "__ non è un costruttore" errore quando provo a 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
Il problema è con
Al momento di scrivere questo, nessun ambiente supporta i moduli ES6 nativamente. Quando li usi in Node.js devi usare qualcosa come Babel per convertire i moduli in CommonJS. Ma come avviene esattamente?
Molte persone considerano module.exports = ...
equivalente a export default ...
e exports.foo ...
equivalente a export const foo = ...
. Questo però non è del tutto vero, o almeno non come lo fa Babel.
Le esportazioni ES6 default
sono in realtà anche esportazioni nominate, tranne che default
è un nome "riservato" e c'è un supporto sintattico speciale per esso. Diamo un'occhiata a come Babel compila le esportazioni con nome e quelle di default:
// 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;
Qui possiamo vedere che l'esportazione di default diventa una proprietà dell'oggetto exports
, proprio come foo
.
Possiamo importare il modulo in due modi: O usando CommonJS o usando la sintassi ES6 import
.
Il tuo problema: Credo che tu stia facendo qualcosa come:
var bar = require('./input');
new bar();
aspettandosi che a bar
venga assegnato il valore dell'esportazione predefinita. Ma come possiamo vedere nell'esempio sopra, l'esportazione predefinita è assegnata alla proprietà default
!
Quindi per accedere all'esportazione predefinita dobbiamo fare
var bar = require('./input').default;
Se usiamo la sintassi del modulo ES6, cioè
import bar from './input';
console.log(bar);
Babel lo trasformerà 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);
Puoi vedere che ogni accesso a bar
è convertito in accesso .default
.
tl;dr in questo momento perché questo funzioni, il file che richiede o importa SlimShady
deve essere compilato usando Babel con 'use strict'
.
Sto usando babel-cli
6.18.0 nel progetto in cui ho inizialmente incontrato questo errore.
'use strict'
è 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