nodejs导出模块方式差异

刚开始学nodejs时看到有的人用exports有的人用module.exports。
我以为是习惯问题,就像定义函数有的人喜欢用funtion f() {} 有的人用 var f = function (){}一样(后来发现这两种定义函数方式也是有区别的。。。区别

后来在cnode上看到有篇文章,发现一般还是不会有完全一样的写法的。

根据nodejs文档,modules是一种简写,在模块加载前被赋予了module.exports的值

The exports variable is available within a module’s file-level scope, and is
assigned the value of module.exports before the module is evaluated.

官网给了一段解释require原理的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

function require(/* ... */) {
const module = { exports: {} };
((module, exports) => {
// Your module code here. In this example, define a function.
function someFunc() {}
exports = someFunc;
// At this point, exports is no longer a shortcut to module.exports, and
// this module will still export an empty default object.
module.exports = someFunc;
// At this point, the module will now export someFunc, instead of the
// default object.
})(module, module.exports);
return module.exports;
}

可以看到require得到的永远是module.exports的值,模块内的exports是指向module.exports的引用(一开始是个空对象),对exports修改最终还是会影响到module.exports的值,所以可以使用exports简写。
但是如果对exports重新赋值,exports就会指向一块新分配的内存空间,而不再指向module.exports,这通常不是我们想要的,这样可能导出的对象还是空的,因为module.exports还是一个空对象。

可以测试下require到的到底是exports还是module.exports

export
1
2
3
4
5
module.exports = {
name: "julien"
}
console.log("module.exports:", module.exports)
console.log("exports:", exports);
import
1
2
let a = require("./export")
console.log(a)

node import.js 查看输出

1
2
3
module.exports: { name: 'julien' }
exports: {}
{ name: 'julien' }

此时exports还是一个空对象,而我们是可以require这个模块的。

恩,反正坚持用module.exports就好了。。。