最近看Node.js的时候,看到有exportsmodule.exports两种导出模块的形式,非常好奇它们有什么区别,于是钻研了一番

Node外面的模块零碎遵循的是CommonJS标准。
那问题又来了,什么是CommonJS标准呢?

CommonJS定义的模块分为: 模块标识(module)、模块定义(exports) 、模块援用(require)

moduleexports都是Node.js中的内置对象,咱们在控制台把它们输入来

console.log(exports)// {}console.log(module)//Module {        //  id: '.',//  path: 'F:\\node\\test',//  exports: {},//  ......//}
能够看进去,exportsmodule中的一个属性,并且都是空对象{},实际上exports是module.exports的一个援用,exports指向的是module.exports,它们指向同一个内存地址,也就是说不扭转它们内存指向的状况下,它们是等价的,即module.exports === exports


当初新建一个a.js用来导出模块,新建一个b.js用来导入模块
应用module.exports的形式导出:

//a.jsmodule.exports.name = 'amy'//b.jsvar a = require('./b.js')console.log(a)  // 输入: { name: 'amy' }

应用exports属性的形式导出:

//a.jsexports.name = 'amy'//b.jsvar a = require('./b.js')console.log(a)  // 输入: { name: 'amy' }

应用exports间接赋值的形式导出:

//a.jsexports = { name: 'amy' }//b.jsvar a = require('./b.js')console.log(a)  // 输入: {}
从输入后果能够看出,应用module.exports和exports属性两种导出形式是一样的,间接给exports赋值的导出形式是有效的

咱们再看《Node.js疾速入门》第三章的一段话

在内部援用该模块时,其接口对象就是要输入的对象自身,而不是原先的exports。

事实上,exports 自身仅仅是一个一般的空对象,即 {},它专门用来申明接口,本
质上是通过它为模块闭包①的外部建设了一个无限的拜访接口。因为它没有任何非凡的中央,
所以能够用其余货色来代替。

不能够通过对 exports 间接赋值代替对 module.exports 赋值。exports 实际上只是一个和 module.exports 指向同一个对象的变量,它自身会在模块执行完结后开释,但 module 不会,因而只能通过指定module.exports 来扭转拜访接口。


总结

require引入的对象实质上是module.exports,尽管应用exports点属性的形式也能够导出,然而为了防止出错,尽量都用 module.exports 导出,而后用require导入。