Qual é a diferença entre Node's module.exports
e ES6's export default
? I'estou tentando descobrir porque eu recebo o "__ não é um construtor" erro quando tento exportar padrão
no 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
A questão é com
No momento de escrever isto, nenhum ambiente suporta os módulos ES6 nativamente. Ao utilizá-los no Node.js você precisa usar algo como Babel para converter os módulos para CommonJS. Mas como isso acontece exatamente?
Muitas pessoas consideram module.exports = ...
equivalente a export default ...
e export.foo ...
equivalente a export const foo = ...
. Isso'não é bem verdade, ou pelo menos não é como Babel o faz.
ES6 default
exportações também são na verdade nome exportações, exceto que default
é um "reserved" nome e há suporte especial de sintaxe para ele. Vamos ver como Babel compila os nomes e exportações padrão:
// 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;
Aqui podemos ver que a exportação padrão se torna uma propriedade no objeto exportação
, assim como o foo
.
Podemos importar o módulo de duas maneiras: Utilizando o CommonJS ou utilizando a sintaxe ES6 importar
.
Sua edição: Acredito que estás a fazer algo parecido:
var bar = require('./input');
new bar();
esperando que bar
seja atribuído o valor da exportação padrão. Mas como podemos ver no exemplo acima, a exportação padrão é atribuída à propriedade default
!
Portanto, para aceder à exportação padrão, temos de fazer
var bar = require('./input').default;
Se utilizarmos a sintaxe do módulo ES6, nomeadamente
import bar from './input';
console.log(bar);
Babel vai transformá-lo para
'use strict';
var _input = require('./input');
var _input2 = _interopRequireDefault(_input);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
console.log(_input2.default);
Você pode ver que todo acesso à bar
é convertido para acesso .default
.
tl;dr neste momento para que isto funcione, o arquivo que requer ou importa o SlimShady
deve ser compilado utilizando Babel com 'use strict'
.
I'm utilizando babel-cli
6.18.0 no projeto onde eu inicialmente encontrei este erro.
'use strict'
is 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