详解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 相关文章推荐
轻松创建nodejs服务器(4):路由
Dec 18 NodeJs
轻松创建nodejs服务器(5):事件处理程序
Dec 18 NodeJs
轻松创建nodejs服务器(6):作出响应
Dec 18 NodeJs
浅析nodejs实现Websocket的数据接收与发送
Nov 19 NodeJs
nodejs如何获取时间戳与时间差
Aug 03 NodeJs
Nodejs中解决cluster模块的多进程如何共享数据问题
Nov 10 NodeJs
详解nodejs操作mongodb数据库封装DB类
Apr 10 NodeJs
详解nodejs模板引擎制作
Jun 14 NodeJs
nodejs 图片预览和上传的示例代码
Sep 30 NodeJs
nodejs async异步常用函数总结(推荐)
Nov 17 NodeJs
通过nodejs 服务器读取HTML文件渲染到页面的方法
May 17 NodeJs
nodejs实现聊天机器人功能
Sep 19 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
实现在同一方法中获取当前方法中新赋值的session值解决方法
2014/06/26 PHP
Zend Framework 2.0事件管理器(The EventManager)入门教程
2014/08/11 PHP
php实现计数器方法小结
2015/01/05 PHP
javascript cookies 设置、读取、删除实例代码
2010/04/12 Javascript
基于jquery的cookie的用法
2011/01/10 Javascript
JQuery切换显示的效果实例代码
2013/02/27 Javascript
jQuery判断div随滚动条滚动到一定位置后停止
2014/04/02 Javascript
封装好的js判断操作系统与浏览器代码分享
2015/01/09 Javascript
js实现touch移动触屏滑动事件
2015/04/17 Javascript
jquery 实现输入邮箱时自动补全下拉提示功能
2015/10/04 Javascript
JS封装的自动创建表格的实现代码
2016/06/15 Javascript
JS实现输入框提示文字点击时消失效果
2016/07/19 Javascript
jQuery实现页面顶部下拉广告
2016/12/30 Javascript
javascript基本数据类型和转换
2017/03/17 Javascript
简单谈谈js的数据类型
2017/09/25 Javascript
Vue如何实现响应式系统
2018/07/11 Javascript
Python中用于去除空格的三个函数的使用小结
2015/04/07 Python
Python实现基于多线程、多用户的FTP服务器与客户端功能完整实例
2017/08/18 Python
在python3环境下的Django中使用MySQL数据库的实例
2017/08/29 Python
Python实现修改文件内容的方法分析
2018/03/25 Python
python如何创建TCP服务端和客户端
2018/08/26 Python
详解Python安装tesserocr遇到的各种问题及解决办法
2019/03/07 Python
pandas 选取行和列数据的方法详解
2019/08/08 Python
Python实现银行账户资金交易管理系统
2020/01/03 Python
Pytorch 神经网络—自定义数据集上实现教程
2020/01/07 Python
Python web如何在IIS发布应用过程解析
2020/05/27 Python
python 常见的反爬虫策略
2020/09/27 Python
ONLY瑞典官网:世界知名服装品牌
2018/06/19 全球购物
Bose加拿大官方网站:美国知名音响品牌
2019/03/21 全球购物
CheapTickets泰国:廉价航班,查看促销价格并预订机票
2019/12/28 全球购物
Linux如何压缩可执行文件
2013/10/21 面试题
教学个人的自我评价分享
2014/02/16 职场文书
办公室文员岗位职责范本
2014/06/12 职场文书
2014年实习班主任工作总结
2014/11/08 职场文书
观看安全警示教育片心得体会
2016/01/15 职场文书
美国运营商 T-Mobile 以 117.83Mb/s 的速度排第一位
2022/04/21 数码科技