详解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打包工具整合到鼠标右键的方法
May 11 NodeJs
nodejs之请求路由概述
Jul 05 NodeJs
详解Nodejs的timers模块
Dec 22 NodeJs
nodejs中全局变量的实例解析
Mar 07 NodeJs
nodejs中使用HTTP分块响应和定时器示例代码
Mar 19 NodeJs
NodeJs模拟登陆正方教务
Apr 28 NodeJs
mac下的nodejs环境安装的步骤
May 24 NodeJs
详解nodejs模板引擎制作
Jun 14 NodeJs
NodeJs中express框架的send()方法简介
Jun 20 NodeJs
nodejs项目windows下开机自启动的方法
Nov 22 NodeJs
NodeJS使用Range请求实现下载功能的方法示例
Oct 12 NodeJs
基于nodejs的雪碧图制作工具的示例代码
Nov 05 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
多文件上传的例子
2006/10/09 PHP
收集的二十一个实用便利的PHP函数代码
2010/04/22 PHP
php实现处理输入转义字符的代码
2015/11/08 PHP
详解php设置session(过期、失效、有效期)
2015/11/12 PHP
PHP 实现浏览记录并按日期分组
2017/05/11 PHP
php实现评论回复删除功能
2017/05/23 PHP
利用PHP访问MySql数据库的逻辑操作以及增删改查的实例讲解
2017/08/30 PHP
深入理解JavaScript系列(2) 揭秘命名函数表达式
2012/01/15 Javascript
Javascript实现DIV滚动自动滚动到底部的代码
2012/03/01 Javascript
为原生js Array增加each方法
2012/04/07 Javascript
使用jQuery插件创建常规模态窗口登陆效果
2013/08/23 Javascript
js数组循环遍历数组内所有元素的方法
2014/01/18 Javascript
jQuery图片特效插件Revealing实现拉伸放大
2015/04/22 Javascript
JS中对象与字符串的互相转换详解
2016/05/20 Javascript
轻松掌握JavaScript单例模式
2016/08/25 Javascript
Angular.js跨controller实现参数传递的两种方法
2017/02/20 Javascript
关于使用axios的一些心得技巧分享
2017/07/02 Javascript
详解ECMAScript typeof用法
2018/07/25 Javascript
vue点击当前路由高亮小案例
2019/09/26 Javascript
js原生map实现的方法总结
2020/01/19 Javascript
python批量修改文件后缀示例代码分享
2013/12/24 Python
在Mac OS系统上安装Python的Pillow库的教程
2015/11/20 Python
python win32 简单操作方法
2017/05/25 Python
python中int与str互转方法
2018/07/02 Python
Python中的上下文管理器相关知识详解
2019/09/19 Python
python爬虫开发之urllib模块详细使用方法与实例全解
2020/03/09 Python
python实现数学模型(插值、拟合和微分方程)
2020/11/13 Python
Linux上比较文件的命令都有哪些
2013/09/28 面试题
夜大自我鉴定
2013/10/31 职场文书
会计出纳岗位职责
2013/12/25 职场文书
青年创业培训欢迎词
2014/01/08 职场文书
关于迟到的检讨书
2014/01/26 职场文书
企业诚信承诺书
2014/05/23 职场文书
2014年药品销售工作总结
2014/12/16 职场文书
小学工作总结2015
2015/05/04 职场文书
python tkinter模块的简单使用
2021/04/07 Python