Node.js和ES6中的module.exports和export默认值
Node的module.exports
和ES6的export default
什么区别? 我试图找出为什么当我尝试在Node.js 6.2.2中export default
时,我得到“__不是构造函数”错误。
什么工作
'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
问题在于
- 在CommonJS中如何模拟ES6模块
- 如何导入模块
ES6到CommonJS
在编写本文时,没有任何环境本身支持ES6模块。 当在Node.js中使用它们时,你需要使用像Babel这样的东西将模块转换为CommonJS。 但是,究竟发生了什么呢?
很多人认为module.exports = ...
等同于export default ...
和exports.foo ...
等同于export const foo = ...
尽pipe如此,至less不是巴贝尔如何做的。
ES6 default
导出实际上也被命名为导出,除了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;
在这里我们可以看到,默认的导出就像foo
一样成为了exports
对象的一个属性。
导入模块
我们可以通过两种方式导入模块:使用CommonJS或使用ES6 import
语法。
你的问题:我相信你正在做这样的事情:
var bar = require('./input'); new bar();
期望该bar
被分配了默认导出的值。 但是,正如我们在上面的例子中看到的那样,默认导出被分配给了default
属性!
所以为了访问默认的导出,我们实际上必须这样做
var bar = require('./input').default;
如果我们使用ES6模块语法,即
import bar from './input'; console.log(bar);
巴别将把它转化为
'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
的文件必须使用'use strict'
巴别编译。
我在最初遇到这个错误的项目中使用了babel-cli
6.18.0。
没有'use strict'
就是坏消息
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