详解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的前后端分离的思考与实践(二)模版探索
Sep 26 NodeJs
nodejs 提示‘xxx’ 不是内部或外部命令解决方法
Nov 20 NodeJs
详解nodejs 文本操作模块-fs模块(四)
Dec 22 NodeJs
Nodejs+Socket.io实现通讯实例代码
Feb 13 NodeJs
nodejs个人博客开发第一步 准备工作
Apr 12 NodeJs
详解nodeJS之二进制buffer对象
Jun 03 NodeJs
nodejs创建简易web服务器与文件读写的实例
Sep 07 NodeJs
详解nodeJs文件系统(fs)与流(stream)
Jan 24 NodeJs
Nodejs下使用gm圆形裁剪并合成图片的示例
Feb 22 NodeJs
详解nodejs解压版安装和配置(带有搭建前端项目脚手架)
Dec 06 NodeJs
nodejs 使用http进行post或get请求的实例(携带cookie)
Jan 03 NodeJs
NVM安装nodejs的方法实用步骤
Jan 16 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
PHP 常见郁闷问题答解
2006/11/25 PHP
PHP使用SOAP扩展实现WebService的方法
2016/04/01 PHP
完整显示当前日期和时间的JS代码
2007/09/17 Javascript
jquery cookie实现的简单换肤功能适合小网站
2013/08/25 Javascript
javascript相等运算符与等同运算符详细介绍
2013/11/09 Javascript
jQuery实现的Tab滑动选项卡及图片切换(多种效果)小结
2015/09/14 Javascript
JS+CSS实现大气清新的滑动菜单效果代码
2015/10/22 Javascript
全面了解js中的script标签
2016/07/04 Javascript
EsLint入门学习教程
2017/02/17 Javascript
解决jquery appaend元素中id绑定事件失效的问题
2017/09/12 jQuery
javascriptvoid(0)含义以及与"#"的区别讲解
2019/01/19 Javascript
vue框架下部署上线后刷新报404问题的解决方案(推荐)
2019/04/03 Javascript
ES6 Iterator接口和for...of循环用法分析
2019/07/31 Javascript
JavaScript Canvas编写炫彩的网页时钟
2019/10/16 Javascript
如何使用JavaScript检测空闲的浏览器选项卡
2020/05/28 Javascript
js实现星星海特效的示例
2020/09/28 Javascript
[02:53]DOTA2英雄基础教程 山岭巨人小小
2013/12/09 DOTA
python cookielib 登录人人网的实现代码
2012/12/19 Python
给Python中的MySQLdb模块添加超时功能的教程
2015/05/05 Python
Python验证码识别的方法
2015/07/10 Python
python字符串替换第一个字符串的方法
2019/06/26 Python
django-filter和普通查询的例子
2019/08/12 Python
Python从MySQL数据库中面抽取试题,生成试卷
2021/01/14 Python
Html5内唤醒百度、高德APP的实现示例
2019/05/20 HTML / CSS
HTML5触摸事件实现移动端简易进度条的实现方法
2018/05/04 HTML / CSS
美国最大的香水出口:FragranceX.com
2017/11/04 全球购物
英国首屈一指的票务公司:See Tickets
2019/05/11 全球购物
Mountain Warehouse德国官网:英国户外零售商
2019/08/11 全球购物
如何处理简单的PHP错误
2015/10/14 面试题
介绍一下Linux中的链接
2016/05/28 面试题
js正则匹配markdown里的图片标签的实现
2021/03/24 Javascript
社区党建工作汇报材料
2014/10/27 职场文书
违反学校规则制度检讨书
2015/01/01 职场文书
2016年小学生清明节广播稿
2015/12/17 职场文书
springboot新建项目pom.xml文件第一行报错的解决
2022/01/18 Java/Android
python数字图像处理之对比度与亮度调整示例
2022/06/28 Python