Node的模块有什么不同?出口和ES6的出口默认?我试图弄清楚为什么当我试图在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

当前回答

问题在于

如何在CommonJS中模拟ES6模块 如何导入模块

CommonJS的ES6

在撰写本文时,还没有环境原生支持ES6模块。当在Node.js中使用它们时,你需要使用像Babel这样的东西来将模块转换为CommonJS。但这究竟是如何发生的呢?

很多人考虑模块。出口=…等效于export default…和出口。喷火……等价于export const foo = ....但这并不完全正确,至少巴别塔不是这么做的。

ES6默认导出实际上也被命名为exports,除了default是一个“保留”名称,并且有特殊的语法支持。让我们看看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; 

在这里,我们可以看到默认的导出变成了exports对象的一个属性,就像foo一样。

导入模块

我们可以用两种方式导入模块:使用CommonJS或使用ES6导入语法。

你的问题:我相信你正在做这样的事情:

var bar = require('./input');
new bar();

期望该栏被分配默认导出的值。但是正如我们在上面的例子中看到的,默认导出被分配给默认属性!

为了访问默认导出,我们需要

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。

其他回答

问题在于

如何在CommonJS中模拟ES6模块 如何导入模块

CommonJS的ES6

在撰写本文时,还没有环境原生支持ES6模块。当在Node.js中使用它们时,你需要使用像Babel这样的东西来将模块转换为CommonJS。但这究竟是如何发生的呢?

很多人考虑模块。出口=…等效于export default…和出口。喷火……等价于export const foo = ....但这并不完全正确,至少巴别塔不是这么做的。

ES6默认导出实际上也被命名为exports,除了default是一个“保留”名称,并且有特殊的语法支持。让我们看看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; 

在这里,我们可以看到默认的导出变成了exports对象的一个属性,就像foo一样。

导入模块

我们可以用两种方式导入模块:使用CommonJS或使用ES6导入语法。

你的问题:我相信你正在做这样的事情:

var bar = require('./input');
new bar();

期望该栏被分配默认导出的值。但是正如我们在上面的例子中看到的,默认导出被分配给默认属性!

为了访问默认导出,我们需要

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。

你需要在你的项目中正确配置babel来使用export default和export const foo

npm install --save-dev @babel/plugin-proposal-export-default-from

然后在.babelrc中添加以下配置

"plugins": [ 
       "@babel/plugin-proposal-export-default-from"
      ]

Felix Kling对这两个进行了很好的比较,对于那些想知道如何在命名exports with module的同时进行导出默认的人来说。在nodejs中导出

module.exports = new DAO()
module.exports.initDAO = initDAO // append other functions as named export

// now you have
let DAO = require('_/helpers/DAO');
// DAO by default is exported class or function
DAO.initDAO()