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

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

或者直接问,node.js的模块功能是怎么实现的。
这样得益于javascript是函数性的语言,并支持闭包。

js的闭包

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

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'; };

参考

liaoxuefeng

exports 和 module.exports 的区别

w3cschool

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

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

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

nodejs里的module.exports和exports相关推荐

  1. nodejs中module.exports和exports的区别

    最近在学习nodejs,这篇文章就权当是一篇笔记,如果有什么地方有误,望指出. 首先我们要明白一个前提,CommonJS模块规范和ES6模块规范完全是两种不同的概念. CommonJS模块规范 Com ...

  2. 一句话说清楚NodeJS中module.exports和exports的区别

    关于这个问题NodeJS的官方文档中有一句很精辟的解释: What's the difference between module.exports and exports? The first exp ...

  3. 【nodejs】import、export、exports、module.exports

    1.import 和 export(ES6特性) 目录结构 export_file.js export const myNumbers = [1, 2, 3, 4]; const animals = ...

  4. module.exports和exports得区别

    对module.exports和exports的一些理解 可能是有史以来最简单通俗易懂的有关Module.exports和exports区别的文章了. exports = module.exports ...

  5. module是什么类型_nodejs中module.exports和exports的区别

    本文同步发表在我的个人博客中: 沧沧凉凉​www.cclliang.com 最近在学习nodejs,这篇文章就权当是一篇笔记,如果有什么地方有误,望指出. 先说说它们之间的区别: exports只能使 ...

  6. vue vue-cli3 修改elementui的date-picker源码 引入node_modules里的element-ui后报错exports is not defined...

    报错说明: 1.复制node_modules/element-ui/packages/date-picker里的文件到自己项目里  --------->>>>>>& ...

  7. module.exports与exports,export与export defa

    首先我们要明白一个前提,CommonJS模块规范和ES6模块规范完全是两种不同的概念. CommonJS模块规范 Node应用由模块组成,采用CommonJS模块规范. 根据这个规范,每个文件就是一个 ...

  8. (node中)module.exports 和exports的区别

    (node中使用)module.exports 和exports的区别是什么? 用一句话来说明就是,require只会去引用module.exports这个对象的导出,不会引用exports对象的,而 ...

  9. 谈谈module.exports和exports

    谈谈module.exports和exports module.exports 对象是由模块系统创建的.在我们自己写模块的时候,需要在模块最后写好模块接口,声明这个模块对外暴露什么内容,module. ...

最新文章

  1. 有关开发的配置的有用信息
  2. Android 数据存储 Room
  3. python文件对象提供了3个读方法、分别是-python3基础之文件对象操作
  4. AutoCompleteTextView的简单用法
  5. POJ 2823 Sliding Window
  6. Drupal 为前台(Front page)页面添加区域(Regions)
  7. linux应用程序是什么,linux下c开发了一个应用程序,它的扩展名是什么?
  8. kickstart安装
  9. 大众宣布成立欧洲公司 负责旗下电动汽车电池业务
  10. 从《觉醒年代》看如何用Python来绘制可视化仪表盘
  11. button添加插槽之后绑定不来事件_javaScript基础事件(二)事件处理程序
  12. Viscosity for Mac(好用的Open客户端)
  13. 最受程序员欢迎的 20 本书!
  14. excel组合汇总_Excel汇总20150302
  15. COSCon'21 人工智能(A)论坛介绍
  16. protobuf在C++和Python的使用
  17. python的自定义函数
  18. js字符串去除空格和中文
  19. 2022完整版搜索引擎优化指南清单(你可以按步骤执行的SEO工作清单)
  20. 使用xpath匹配猫眼top100标题名(萌新简化版)

热门文章

  1. 【机器学习】 - 使用dlib进行人脸定位,人脸检测,给人脸图片戴口罩
  2. 【HDU - 5943】Kingdom of Obsession(数论,素数间隔结论,构造,思维,匈牙利算法,匹配问题)
  3. 【Hihocoder - offer编程练习赛39 - D】前缀后缀查询(后缀字典树,哈希,思维)
  4. 【POJ - 2378】Tree Cutting(树形dp,树的重心变形)
  5. 【计蒜客 - 蓝桥训练】欧拉函数(数学,数论,模板)
  6. C语言编程中关于负数的%运算的判定。
  7. Apollo进阶课程㉝丨Apollo ROS原理—2
  8. Apollo进阶课程㉙丨Apollo控制技术详解——控制器的类型
  9. 通过反射获得类的构造引用无视private修饰符
  10. Spring,ehcache整合报错