Node.js中为什么不能直接将exports赋值为对象?
当我们引用模块时,常用exports.a=1,或者medule.exports={a:1,b:"hahaha"}的方式对外暴露对象,可为什么不可以直接exports={a:1,b:"hahaha"}呢?
首先思考到一个问题:为什么可以直接通过exports.a的方式定义属性呢?
虽然我们并没有创建过exports,但是在Node.js的node-globals-stub.js中为我们提前定义好了var exports={},因此我们可以方便地直接使用(注意exports并不是全局对象),但实际上,这个伪全局exports对象并不是module里的属性exports!!!有图有真相:
伪全局exports:
module中的exports:
1.从这里可以看出,同属于node-globals-stub.js,module中的属性exports指向伪全局对象exports,因此在内存里是这样的(暂时简易成这样):
2.因此,不管我们是通过exports.a还是module.exports.a去对外暴露,得到的效果都是:
3.但是如果我们直接让exports={a:1,b:"haahah},就会导致伪全局exports创建新的对象,而module.exports仍然指向之前的对象:
这也是为什么使用exports={....}后会导致伪全局exports彻底失效,之后哪怕乖乖地用exports.a=1也没用,因为module中的属性exports将永远指向之前的那个伪全局exports对象。
4.那为什么module.exports可以正常使用并且不受影响呢?
那是因为module.exports的指向才是require方法的真正返回值,接着上面的图执行module.exports={c:2,d:"yayaya}:
但是注意,使用module.exports={....}也会导致exports失效。