详解nodejs中exports和module.exports的区别


Posted in NodeJs onFebruary 17, 2017

require 用来加载代码,而 exports 和 module.exports 则用来导出代码。但很多新手可能会迷惑于 exports 和 module.exports 的区别,为了更好的理解 exports 和 module.exports 的关系,我们先来巩固下 js 的基础。示例:

app.js

var a = {name: 'nswbmw 1'};
var b = a;
console.log(a);
console.log(b);
b.name = 'nswbmw 2';
console.log(a);
console.log(b);
var b = {name: 'nswbmw 3'};
console.log(a);
console.log(b);

运行 app.js 结果为:

{ name: 'nswbmw 1' }
{ name: 'nswbmw 1' }
{ name: 'nswbmw 2' }
{ name: 'nswbmw 2' }
{ name: 'nswbmw 2' }
{ name: 'nswbmw 3' }

解释一下:a 是一个对象,b 是对 a 的引用,即 a 和 b 指向同一个对象,即 a 和 b 指向同一块内存地址,所以前两个输出一样。当对 b 作修改时,即 a 和 b 指向同一块内存地址的内容发生了改变,所以 a 也会体现出来,所以第三、四个输出一样。当对 b 完全覆盖时,b 就指向了一块新的内存地址(并没有对原先的内存块作修改),a 还是指向原来的内存块,即 a 和 b 不再指向同一块内存,也就是说此时 a 和 b 已毫无关系,所以最后两个输出不一样。

明白了上述例子后,我们进入正题。

我们只需知道三点即可知道 exports 和 module.exports 的区别了:

  • exports 是指向的 module.exports 的引用
  • module.exports 初始值为一个空对象 {},所以 exports 初始值也是 {}
  • require() 返回的是 module.exports 而不是 exports

所以:我们通过

var name = 'nswbmw';
exports.name = name;
exports.sayName = function() {
 console.log(name);
}

给 exports 赋值其实是给 module.exports 这个空对象添加了两个属性而已,上面的代码相当于:

var name = 'nswbmw';
module.exports.name = name;
module.exports.sayName = function() {
 console.log(name);
}

我们通常这样使用 exports 和 module.exports

一个简单的例子,计算圆的面积:

使用 exports

app.js

var circle = require('./circle');
console.log(circle.area(4));

circle.js

exports.area = function(r) {
 return r * r * Math.PI;
}

使用 module.exports

app.js

var area = require('./area');
console.log(area(4));

area.js

module.exports = function(r) {
 return r * r * Math.PI;
}

上面两个例子输出是一样的。你也许会问,为什么不这样写呢?

app.js

var area = require('./area');
console.log(area(4));

area.js

exports = function(r) {
 return r * r * Math.PI;
}

运行上面的例子会报错。这是因为,前面的例子中通过给 exports 添加属性,只是对 exports 指向的内存做了修改,而

exports = function(r) {
 return r * r * Math.PI;
}

其实是对 exports 进行了覆盖,也就是说 exports 指向了一块新的内存(内容为一个计算圆面积的函数),也就是说 exports 和 module.exports 不再指向同一块内存,也就是说此时 exports 和 module.exports 毫无联系,也就是说 module.exports 指向的那块内存并没有做任何改变,仍然为一个空对象 {} ,也就是说 area.js 导出了一个空对象,所以我们在 app.js 中调用 area(4) 会报 TypeError: object is not a function 的错误。

所以,一句话做个总结:当我们想让模块导出的是一个对象时,exports 和 module.exports 均可使用(但 exports也不能重新覆盖为一个新的对象),而当我们想导出非对象接口时,就必须也只能覆盖 module.exports。

我们经常看到这样的用写法:

exports = module.exports = somethings;

上面的代码等价于

module.exports = somethings;
exports = module.exports;

原因也很简单,module.exports = somethings 是对 module.exports 进行了覆盖,此时 module.exports 和 exports 的关系断裂,module.exports 指向了新的内存块,而 exports 还是指向原来的内存块,为了让 module.exports 和 exports 还是指向同一块内存或者说指向同一个 “对象”,所以我们就 exports = module.exports。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

NodeJs 相关文章推荐
14款NodeJS Web框架推荐
Jul 11 NodeJs
基于NodeJS的前后端分离的思考与实践(一)全栈式开发
Sep 26 NodeJs
详解nodejs微信公众号开发——4.自动回复各种消息
Apr 11 NodeJs
详解nodejs的express如何自动生成项目框架
Jul 12 NodeJs
nodejs对express中next函数的一些理解
Sep 08 NodeJs
基于nodejs实现微信支付功能
Dec 20 NodeJs
Mac下通过brew安装指定版本的nodejs教程
May 17 NodeJs
nodejs用gulp管理前端文件方法
Jun 24 NodeJs
nodejs aes 加解密实例
Oct 10 NodeJs
nodejs 使用 js 模块的方法实例详解
Dec 04 NodeJs
浅谈使用nodejs搭建web服务器的过程
Jul 20 NodeJs
NodeJS和浏览器中this关键字的不同之处
Mar 03 NodeJs
Nodejs+Socket.io实现通讯实例代码
Feb 13 #NodeJs
Nodejs高扩展性的模板引擎 functmpl简介
Feb 13 #NodeJs
Nodejs 发送Post请求功能(发短信验证码例子)
Feb 09 #NodeJs
Nodejs实现短信验证码功能
Feb 09 #NodeJs
Express与NodeJs创建服务器的两种方法
Feb 06 #NodeJs
使用nodejs下载风景壁纸
Feb 05 #NodeJs
nodeJs链接Mysql做增删改查的简单操作
Feb 04 #NodeJs
You might like
escape unescape的php下的实现方法
2007/04/27 PHP
Wordpress 相册插件 NextGEN-Gallery 添加目录将中文转为拼音的解决办法
2010/12/29 PHP
PHP中遇到BOM、编码导致json_decode函数无法解析问题
2014/07/02 PHP
Yii中CArrayDataProvider和CActiveDataProvider区别实例分析
2016/03/02 PHP
基于PHP实现商品成交时发送短信功能
2016/05/11 PHP
使用 laravel sms 构建短信验证码发送校验功能
2017/11/06 PHP
简单JS代码压缩器
2006/10/12 Javascript
JS获取URL中参数值(QueryString)的4种方法分享
2014/04/12 Javascript
更快的异步执行(setTimeout多浏览器)
2014/08/12 Javascript
深入理解JavaScript中为什么string可以拥有方法
2016/05/24 Javascript
JS中parseInt()和map()用法分析
2016/12/16 Javascript
Jquery Easyui搜索框组件SearchBox使用详解(19)
2016/12/17 Javascript
vue实现ajax滚动下拉加载,同时具有loading效果(推荐)
2017/01/11 Javascript
微信小程序左滑动显示菜单功能的实现
2018/06/14 Javascript
js正则表达式校验指定字符串的方法
2018/07/23 Javascript
浅谈vue同一页面中拥有两个表单时,的验证问题
2018/09/18 Javascript
微信小程序列表中item左滑删除功能
2018/11/07 Javascript
JavaScript实现背景自动切换小案例
2019/09/27 Javascript
vant 中van-list的用法说明
2020/11/11 Javascript
如何在Python中编写并发程序
2016/02/27 Python
用Python解决x的n次方问题
2019/02/08 Python
Python数据可视化:箱线图多种库画法
2019/11/06 Python
matplotlib.pyplot画图并导出保存的实例
2019/12/07 Python
Python实现文件压缩和解压的示例代码
2020/08/12 Python
详解Python3 定义一个跨越多行的字符串的多种方法
2020/09/06 Python
解决pycharm导入numpy包的和使用时报错:RuntimeError: The current Numpy installation (‘D:\\python3.6\\lib\\site-packa的问题
2020/12/08 Python
运动会稿件50字
2014/02/17 职场文书
法人代表授权委托书
2014/04/08 职场文书
公司请假条范文
2014/04/11 职场文书
银行竞聘上岗演讲稿
2014/09/12 职场文书
2016继续教育培训学习心得体会
2016/01/19 职场文书
Python机器学习之基于Pytorch实现猫狗分类
2021/06/08 Python
低版本Druid连接池+MySQL驱动8.0导致线程阻塞、性能受限
2021/07/01 MySQL
分布式架构Redis中有哪些数据结构及底层实现原理
2022/03/13 Redis
ICOM R71E和R72E图文对比解说
2022/04/07 无线电
Docker与K8s关系介绍不会Docker也可以使用K8s
2022/06/25 Servers