Common JS规范

  1. 模块的引用: require()
  2. 模块的定义:
    1. module.exports 唯一导出方式;但是也可以 exports.xx = aa…; 不能 exports = {}; 因为 node 中最后默认导出的是 module.exports,能用 exports.xx = aa 是因为 exports = module.exports;
    2. 模块的标识: 以./ ../ 开头

模块

  1. node中一个 js文件 就是一个模块
  2. 每一个js文件中的 js代码 都是独立运行在一个函数中,而不是在全局中

module.exports vs exports:

  1. 对module.exports赋值:
  1. function hello() {
  2. console.log('Hello, world!');
  3. }
  4. function greet(name) {
  5. console.log('Hello, ' + name + '!');
  6. }
  7. module.exports = {
  8. hello: hello,
  9. greet: greet
  10. };
  1. 直接使用 exports:
  1. function greet(name) {
  2. console.log('Hello, ' + name + '!');
  3. }
  4. function hello() {
  5. console.log('Hello, world!');
  6. }
  7. exports.hello = hello;
  8. exports.greet = greet;
  1. 不可以直接对 exports 赋值:
  1. // 代码可以执行,但是模块并没有输出任何变量:
  2. exports = {
  3. hello: hello,
  4. greet: greet
  5. };

exports 对象如果没有 赋值的话,其实就是对 module.exports 的引用,我们可以用 exports.xxx 添加新的属性,但是如果直接对 exports 赋值,exports 就不再是对 module.exports 的引用,所以 __module.exports 仍然为空对象 {}。

结论:

  1. 如果要输出一个键值对象{}, 可以利用 exports 这个已存在的空对象 {}, 并继续在上面添加新的键值;
  2. 如果要输出一个函数或数组,必须直接对 module.exports 对象赋值;
  3. 因此,直接对 module.exports 赋值,可以应对任何情况 。

深入了解模块原理

Node 如何实现各模块间变量不冲突

JavaScript是一种函数式编程语言,它支持闭包。如果我们把一段JavaScript代码用一个函数包装起来,这段代码的所有“全局”变量就变成了函数内部的局部变量。


  • 当我们在 js 文件中按如下编写代码:
  1. var s = 'Hello';
  2. var name = 'world';
  3. console.log(s + ' ' + name + '!');
  • Node.js加载了js文件 后,它可以把代码包装一下,变成这样执行:
  1. (function () {
  2. // 读取的hello.js代码:
  3. var s = 'Hello';
  4. var name = 'world';
  5. console.log(s + ' ' + name + '!');
  6. // hello.js代码结束
  7. })();

这样一来,原来的全局变量s现在变成了匿名函数内部的局部变量。如果Node.js继续加载其他模块,这些模块中定义的“全局”变量s也互不干扰


模块的输出module.exports的实现

  1. // 准备module对象:
  2. var module = {
  3. id: 'hello',
  4. exports: {}
  5. };
  6. var load = function (module) {
  7. // 读取的hello.js代码:
  8. function greet(name) {
  9. console.log('Hello, ' + name + '!');
  10. }
  11. module.exports = greet;
  12. // hello.js代码结束
  13. return module.exports;
  14. };
  15. var exported = load(module);
  16. // 保存module:
  17. save(module, exported);
  • 可见,变量module是Node在加载js文件前准备的一个变量,并将其传入加载函数,我们在hello.js中可以直接使用变量module原因就在于它实际上是函数的一个参数:
  1. module.exports = greet;
  • 通过把参数module传递给load()函数,hello.js就顺利地把一个变量传递给了Node执行环境,Node会把module变量保存到某个地方。

  • 由于Node保存了所有导入的module,当我们用require()获取module时,Node找到对应的module,把这个moduleexports变量返回,这样,另一个模块就顺利拿到了模块的输出

——参考地址——