Node'のmodule.exports
とES6'のexport default
の違いは何ですか?Node.js 6.2.2 で export default
を実行しようとすると、 "__ is not a constructor" エラーが発生する理由を解明しようとしています。
'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
との問題があります。
この記事を書いている時点では、ES6モジュールをネイティブにサポートしている環境はありません。Node.jsで使用する場合は、Babelのようなものを使ってモジュールをCommonJSに変換する必要があります。しかし、具体的にはどのようにして変換するのでしょうか?
多くの人は、module.exports = ...
は export default ...
と同じであり、exports.foo ...
は export const foo = ...
と同じであると考えています。しかし、それは正確ではありませんし、少なくとも Babel ではそうなっていません。
ES6 の default
エクスポートは、実際には 名前付き エクスポートでもありますが、default
は "reserved" の名前であり、そのための特別な構文サポートがあります。Babel がどのように名前付きおよびデフォルトのエクスポートをコンパイルするかを見てみましょう。
// 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;
ここでは、デフォルトのエクスポートが foo
と同様に exports
オブジェクトのプロパティになっていることがわかります。
モジュールをインポートするには2つの方法があります。CommonJS を使用するか、ES6 の import
構文を使用するかです。
あなたの問題: あなたは次のようなことをしていると思います。
var bar = require('./input');
new bar();
のように、bar
にデフォルトのエクスポートの値が割り当てられることを期待しています。しかし、上の例でわかるように、デフォルトのエクスポートは default
プロパティに割り当てられています!
つまり、デフォルトのエクスポートにアクセスするには、実際には次のようにしなければなりません。
var bar = require('./input').default;
ES6のモジュール構文を使う場合、つまり
import bar from './input';
console.log(bar);
Babelはこれを
'use strict';
var _input = require('./input');
var _input2 = _interopRequireDefault(_input);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
console.log(_input2.default);
barへのすべてのアクセスが
.default` へのアクセスに変換されていることがわかります。
tl;dr 現在、これを動作させるためには、SlimShady
を要求またはインポートしているファイルは、Babelを使って 'use strict'
でコンパイルする必要があります。
私が最初にこのエラーに遭遇したプロジェクトでは、babel-cli
6.18.0を使用しています。
'use strict'
がないと、Bad News Bears になります。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