你真的会用exports和module.exports吗?

Node中有两个概念exports和module.exports很让人迷惑,雾里看花一般的捉摸不透,本文结合测试来告诉你二者的潜规则…..
commonjs

潜规则

我们知道CommonJS规定,每个模块内部都有个module变量代表它,而module变量有个exports属性。为了方便,Node为每个模块提供了一个exports变量指向module.exports。
exports

记住exoprts和module.exports二者潜规则如下:

  • 加载的模块返回的总是module.exports;
  • 二者默认的指向同一个object对象引用,建立关联关系;
  • 一旦二者不通过属性向此object添加扩展,关联关系就会断开,各自有独立的内存空间;

验证前准备

为了后续测试的顺利,我准备了两个文件:

├── app.js //启动入口
├── base-module.js //模块

app.js用作程序启动的入口,内容如下

// ./app.js
var base=require('./base-module');
console.log(base.name);

base-module.js用于模块定义,后面的代码都在此文件中编写。

验证正常

先来看看正常的情况:在base-module.js中编码如下

exports.name='zqf-blog';


module.exports.name='zqf-blog';

执行 node app.js 即可以看到输出 zqf-blog。也能看到exports和module.exports
exports-module.exports正常

module.exports赋值

// ./base-module.js
module.exports={};
exports.name='zqf-blog';

两条语句顺序无关,执行都输出 undefined,不能理解为module.exports指向一个对象,而exports.name就可以向这个对象添加name属性!其实二者已经断开了关系,各自有独立的内控空间。
exports-invalid

exports赋值

// ./base-module.js
exports={};
exports.name='zqf-blog';

执行输出 undefined,当给exports赋时,二者已经断开了关系,各自有独立的内控空间,他们的值和上例同样
exports-invalid

总是返回module.exports

// ./base-module.js
exports={};
exports.name="exportName"
module.exports.name="zqf-blog";

执行输出 zqf-blog,exports.name和module.exports.name不同,返回的是后者
exports-invalid

学会分析

// ./base-module.js
module.exports = '';
module.exports.name = 'zqf-blog';
exports.name = 'exportName';

猜猜看执行会输出zqf-blog吗?

实际上输出undefined,因为module.exports不再是对象,不具有name属性
exports-invalid

总结

不管千变万化,只要记住上面的三条潜规则,就不再会搞错了,你就真的懂得如何使用exports和module.exports了,如果你还不懂,那就只记得第一条吧,这样任何时候你都使用module.exports就不会错。

翟前锋 wechat
欢迎订阅我的微信公众号:zhaiqianfeng!