博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
nodejs里的module.exports和exports
阅读量:4641 次
发布时间:2019-06-09

本文共 2340 字,大约阅读时间需要 7 分钟。

在node.js中我们可以使用module.exports和exports导出模块,设置导出函数、数组、变量等等

为什么可以用这两个模块?

或者直接问,node.js的模块功能是怎么实现的。

这样得益于javascript是函数性的语言,并支持闭包。

js的闭包

直接看w3cschool吧,感觉讲的挺好的:

node.js的模块实现,大致代码

首先准备一个nodejs规范的代码:

hello.js

var s = 'Hello';var name = 'world';console.log(s + ' ' + name + '!');

Node.js加载了hello.js后,它把这段代码包装一下,大概变成这样:

var module = {    id: 'hello',    exports: {}};var load = function () {    // 实际我们自己编写的hello.js代码:    function greet(name) {        console.log('Hello, ' + name + '!');    }    module.exports = greet;    // hello.js代码结束    return module.exports;};var exports = load();// 保存module:save(module, exports);

module是nodejs自动加的一个对象,可见,初始化的时候会先对module.exports赋值一个空的对象{}。

save(module, exports);这个函数是个真·全局函数,作用是把exports这个变量存到某个全局变量中。其它模块通过require()函数实际上就是去这个全局变量里把对应的值拿出来。

这样,看js代码大概就明白了,为什么在nodejs里可以直接用module.exports和exports这两个语法。

module.exports和exports

module.exports和exports实际上都是对一个对象的引用,这个对象初始化就是一个空对象{}。所以直接就可以使用类似

示例一:module.exports.foo = function () { return 'foo'; };module.exports.bar = function () { return 'bar'; };或者示例二:exports.foo = function () { return 'foo'; };exports.bar = function () { return 'bar'; };

这两个示例作用是一样的,其本质都是往最开始初始化的空数组里添加成员。

示例三module.exports = {    hello: hello,    greet: greet};

示例三就不一样了,实际上module.exports重新引用到了一个新的对象里。如果示例三前面有示例一或者二的代码,那么会最终导致示例一或者二导出的模块丢掉。

示例四exports = {    hello: hello,    greet: greet};

示例四看上去虽然和示例三差不多,但是这种写法实际上并没有输出任何变量!注意看nodejs的实现代码,load()函数里最后return的是module.exports,也就是说最后save的是module.exports的引用对象,而示例四中exports被赋值了一个新的对象,此时module.exports和exports引用的已经不是同一个对象了!

那么提问:示例三虽然对module.exports重新引用到了一个新的对象,最终结果也能实现模块的正常导出,那么示例三里的exports此时引用的是什么对象呢?

最后,如果你打算导出一个数组或者变量,或者函数,都会涉及到module.exports原引用对象的丢弃,要额外注意,此时要小心不要丢掉前面已经导出的模块。

结论

如果要输出一个键值对象{},可以利用exports这个已存在的空对象{},并继续在上面添加新的键值;

如果要输出一个函数或数组,必须直接对module.exports对象赋值。

所以我们可以得出结论:直接对module.exports赋值,可以应对任何情况:

module.exports = {    foo: function () { return 'foo'; }};或者:module.exports = function () { return 'foo'; };

最终,我们强烈建议使用module.exports = xxx的方式来输出模块变量,这样,你只需要记忆一种方法。

或者使用我喜欢的方法,对空对象直接添加值:

var foo = function () { return 'foo'; };...module.exports.foo = foo;//module.exports.bar = function () { return 'bar'; };

参考

,但是我不是很同意文中所说的按共享传递这名字的叫法。实际上无论传递普通变量还是传递函数,都是按值拷贝传递,只不过传递对象的时候,拷贝过去的是个引用变量罢了,即引用副本。

这里就是c语言指针的思想。

如果你对我上面所讲的还不明白,建议去把c语言里的指针好好的重学一遍。真正理解透彻了c里面的指针,学起来其它所有语言都不怕。

转载于:https://www.cnblogs.com/acbingo/p/7709363.html

你可能感兴趣的文章
C#实现 单点登录(SSO)
查看>>
高精度计算(2015.8.1)
查看>>
cocos2d-x tile map瓦片地图的黑线及地图抖动解决方案
查看>>
软工网络15团队作业2——团队计划
查看>>
Android屏幕适配
查看>>
springboot切换配置
查看>>
git
查看>>
ps简单操作文档
查看>>
正则表达式怎么来验证输入框中只能输入整数而且不能以0开头;就是不能输入001这样的数字...
查看>>
笔记26 | Android获取系统时间的几种种方式
查看>>
查询数据库中满足条件的特定行数据
查看>>
ios 向类中动态添加方法
查看>>
从记忆化搜索到动态规划
查看>>
[Network Architecture]Mask R-CNN论文解析(转)
查看>>
集合set
查看>>
Struts2使用通配符加载配置文件和通配符方法的底层实现学习
查看>>
微信小程序简要学习(二)
查看>>
CSS 初探
查看>>
签名应用例子
查看>>
全国城市中心点(全)
查看>>