Node'un module.exports
ile ES6'nın export default
arasındaki fark nedir? Node.js 6.2.2de
export default` yapmaya çalıştığımda neden "__ is not a constructor" hatası aldığımı anlamaya çalışıyorum.
'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
Sorun şu ki
Bu yazının yazıldığı sırada hiçbir ortam ES6 modüllerini yerel olarak desteklememektedir. Bunları Node.js'de kullanırken modülleri CommonJS'ye dönüştürmek için Babel gibi bir şey kullanmanız gerekir. Ama bu tam olarak nasıl gerçekleşiyor?
Birçok kişi module.exports = ...
ifadesini export default ...
ve exports.foo ...
ifadesini de export const foo = ...
ifadesine eşdeğer görmektedir. Ancak bu tam olarak doğru değildir ya da en azından Babel'in yaptığı gibi değildir.
ES6 default
dışa aktarımları aslında adlandırılmış dışa aktarımlardır, ancak default
bir "reserved" adıdır ve bunun için özel sözdizimi desteği vardır. Babel'in named ve default exportları nasıl derlediğine bir göz atalım:
// 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;
Burada, varsayılan dışa aktarımın foo
gibi exports
nesnesi üzerinde bir özellik haline geldiğini görebiliriz.
Modülü iki şekilde içe aktarabiliriz: Ya CommonJS kullanarak ya da ES6 import
sözdizimini kullanarak.
Sorununuz: Sanırım şöyle bir şey yapıyorsunuz:
var bar = require('./input');
new bar();
'bar'a varsayılan dışa aktarma değerinin atanmasını bekler. Ancak yukarıdaki örnekte görebileceğimiz gibi, varsayılan dışa aktarma default
özelliğine atanmıştır!
Yani varsayılan dışa aktarıma erişmek için aslında yapmamız gereken
var bar = require('./input').default;
ES6 modül sözdizimini kullanırsak, yani
import bar from './input';
console.log(bar);
Babel onu
'use strict';
var _input = require('./input');
var _input2 = _interopRequireDefault(_input);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
console.log(_input2.default);
bara yapılan her erişimin
.default` erişimine dönüştürüldüğünü görebilirsiniz.
tl;dr şu anda bunun çalışması için, SlimShady
gerektiren veya içe aktaran dosya Babel kullanılarak 'use strict'
ile derlenmelidir.
Bu hatayla ilk karşılaştığım projede babel-cli
6.18.0 kullanıyorum.
'use strict'
olmadan Kötü Haber Ayıları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