详解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文件操作模块FS(File System)常用函数简明总结
Jun 05 NodeJs
nodejs中转换URL字符串与查询字符串详解
Nov 26 NodeJs
浅谈NodeJS中require路径问题
May 07 NodeJs
nodejs body-parser 解析post数据实例
Jul 26 NodeJs
nodeJS模块简单用法示例
Apr 21 NodeJs
Nodejs实现多文件夹文件同步
Oct 17 NodeJs
nodejs中函数的调用实例详解
Oct 31 NodeJs
详解nodejs解压版安装和配置(带有搭建前端项目脚手架)
Dec 06 NodeJs
nodejs简单抓包工具使用详解
Aug 23 NodeJs
nodejs实现UDP组播示例方法
Nov 04 NodeJs
Nodejs + Websocket 指定发送及群聊的实现
Jan 09 NodeJs
nodejs+express最简易的连接数据库的方法
Dec 23 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蜘蛛统计插件只要有mysql就可用
2010/10/12 PHP
php实现异步将远程链接上内容(图片或内容)写到本地的方法
2016/11/30 PHP
php json相关函数用法示例
2017/03/28 PHP
ThinkPHP+EasyUI之ComboTree中的会计科目树形菜单实现方法
2017/06/09 PHP
Avengerls vs KG BO3 第二场2.18
2021/03/10 DOTA
一些常用的Javascript函数
2006/12/22 Javascript
EXT窗口Window及对话框MessageBox
2011/01/27 Javascript
IE6浏览器下resize事件被执行了多次解决方法
2012/12/11 Javascript
javascript实现简单的Map示例介绍
2013/12/23 Javascript
比较不错的JS/JQuery显示或隐藏文本的方法
2014/02/13 Javascript
jQuery获取标签文本内容和html内容的方法
2015/03/27 Javascript
javascript实现全局匹配并替换的方法
2015/04/27 Javascript
JavaScript的RequireJS库入门指南
2015/07/01 Javascript
Jquery zTree 树控件异步加载操作
2016/02/25 Javascript
Angular2-primeNG文件上传模块FileUpload使用详解
2017/01/14 Javascript
Easyui笔记2:实现datagrid多行删除的示例代码
2017/01/14 Javascript
vue2.0结合DataTable插件实现表格动态刷新的方法详解
2017/03/17 Javascript
JavaScript高阶函数_动力节点Java学院整理
2017/06/28 Javascript
Vue.js学习笔记之常用模板语法详解
2017/07/25 Javascript
微信小程序之几种常见的弹框提示信息实现详解
2019/07/11 Javascript
layui的数据表格+springmvc实现搜索功能的例子
2019/09/28 Javascript
[04:03]辉夜杯主赛事 12月25日RECAP精彩回顾
2015/12/26 DOTA
调试Python程序代码的几种方法总结
2015/04/28 Python
Python Web框架Tornado运行和部署
2020/10/19 Python
Python安装selenium包详细过程
2019/07/23 Python
python 如何对logging日志封装
2020/12/02 Python
英国领先的鞋类零售商:Shoe Zone
2018/12/13 全球购物
皇家阿尔伯特英国官方商店:Royal Albert骨瓷
2019/03/25 全球购物
英国Radley包德国官网:Radley London德国
2019/11/18 全球购物
考博自荐信
2013/10/25 职场文书
项目投资建议书
2014/05/16 职场文书
离婚财产处理协议书
2014/09/30 职场文书
运动会闭幕词
2015/01/28 职场文书
手机销售员岗位职责
2015/04/11 职场文书
排查并解决MySQL生产库内存使用率高的报警
2022/04/11 MySQL
Redis批量生成数据的实现
2022/06/05 Redis