前言

关于Node.js中的exports和module.exports,很多时候都比较容易让人混淆,弄不清楚两者间的区别。那么我们就从头开始理清这两者之间的关系。

来源

在开发Node.js应用的时候,很多模块都是需要引入才能使用,但是为什么exports和module.exports我们没有引用却可以直接使用呢?

事实上,Node.js应用在编译的过程中会对JavaScript文件的内容进行头尾的封装。例如:

// hello.js
const hello = function () {console.log('Hello world');
}
module.exports = {hello
}
// 头尾封装后的js代码
(function (exports, require, module, __filename, __dirname) {const hello = function () {console.log('Hello world');}module.exports = {hello}
})

在进行了头尾封装之后,各个模块之间进行了作用域隔离,避免了污染全局变量,同时可以使每个模块在不引入这些变量的情况下可以使用它们。这些变量依次为当前模块的exports属性、require()方法、当前模块自身(module)、在文件系统中的完整路径、文件目录。

区别

按照Node.js的解释,exports是module对象的一个属性,那么exports和module.exports应该是等价的。的确如初,初始化的exports和module.exports变量的值均为{},代码验证:

// hello.js
const hello = function () {console.log('Hello world');
}
console.log('初始值==========');
console.log(exports);
console.log(module.exports);
module.exports = {hello
}
// 输出结果
初始值==========
{}
{}

可以发现,module对象的exports属性和exports均指向一个空对象{},那么在导出对象的时候使用exports和module.exports有什么区别呢?

我们在使用require()方法引入模块的时候,其实是引入了module.exports对象, exports只是module对象的exports的一个引用,我们可以通过修改exports所指向对象的值来协助修改module.exports的值。

  • 使用exports导出
const hello = function () {console.log('Hello world');
}
exports.hello = {hello
}
console.log('修改值==========');
console.log(exports);
console.log(module.exports);
// 输出结果
修改值==========
{ hello: { hello: [Function: hello] } }
{ hello: { hello: [Function: hello] } }

由于exports和module.exports指向同一块内存区域,所以我们修改exports对象的数据,那么module.exports也会随之改变。

  • 使用module.exports导出
// hello.js
const hello = function () {console.log('Hello world');
}
module.exports = {hello
}
console.log('修改值==========');
console.log(exports);
console.log(module.exports);
// 输出结果
修改值==========
{}
{ hello: [Function: hello] }

你会发现修改后的exports依然是{},而module.exports的值已经改变,这是由于当你给module.exports是直接等于一个新的对象,那么其将指向一块新的内存区域,而此时exports指向的仍然是之前的内存区域,所以二者的值会不一样,但是此时你在其他文件内引入hello.js文件,仍然可以调用hello()方法,这也说明了导出的是module.exports而不是exports。

  • 给exports直接赋值
// hello.js
const hello = function () {console.log('Hello world');
}
exports = {hello
}
console.log('修改值==========');
console.log(exports);
console.log(module.exports);
// 输出结果
修改值==========
{ hello: [Function: hello] }
{}

使用这种方法导出在其他文件调用hello方法即会报错,因为该文件模块导出的对象为空,当然也不可能有hello()方法,这种问题的原因同样是指向的内存区域发生变化所导致的。

总结

  1. exports对象是module对象的一个属性,在初始时exports和module.exports是指向同一块内存区域的;
  2. 在不改变exports内存指向的情况下,修改exports的值可以改变module.exports的值;
  3. 导出尽量使用module.exports以避免混淆。

node.js中exports与module.exports的区别分析相关推荐

  1. Node.js中exports、module.exports、require之间的关系

    Node中的js文件 Node中的每个JS文件都是一个单独的模块,模块中包含的核心变量:exports.module.exports.require nodejs中module文档 // 插入图片 E ...

  2. Node.js 中的 module.exports 与 exports

    介绍 module:每个模块中都有 module 对象,存放了当前模块相关的信息: module.exports:模块导出的内容: exports:默认情况下,exports 和 module.exp ...

  3. Node.js 中 exports 和 module.exports 的区别

    每一个模块中都有一个 module 对象, module 对象中有一个 exports 对象 我们可以把需要导出的成员都放到 module.exports 这个接口对象中,也就是 module.exp ...

  4. Node.js学习之(第二章:exports和module.exports)

    前言 Node中,每个模块都有一个exports接口对象,我们需要把公共的方法或者字符串挂载在这个接口对象中,其他的模块才可以使用. Node.js中只有模块作用域,默认两个模块之间的变量,方法互不冲 ...

  5. Node.js: exports 和 module.exports 的区别

    我理解的exports 和 module.exports 的区别,欢迎大家吐槽~ 为了更好的理解 exports 和 module.exports 的关系,我们先来补点 js 基础.示例: app.j ...

  6. Node.js中exports和moudle.exports

    在Node.js模块化中,首先了解模块化作用域. 和函数作用域类似,在自定义模块中,定义的变量.方法等成员,只能在当前模块内被访问,这种模块级别的访问限制,叫做模块作用域. 可以防止 全局作用域的变量 ...

  7. nodejs中的exports和module.exports

    module是随文件而生的全局变量,它有exports属性,这个属性默认是一个空的字典. node的设计者画蛇添足有定义了一个exports全局变量,export指向module.exports所指向 ...

  8. node.js中模块_在Node.js中需要模块:您需要知道的一切

    node.js中模块 by Samer Buna 通过Samer Buna 在Node.js中需要模块:您需要知道的一切 (Requiring modules in Node.js: Everythi ...

  9. 如何在node.js中发出HTTP POST请求?

    如何在node.js中使用数据发出出站HTTP POST请求? #1楼 如果您使用请求库,这会变得更容易. var request = require('request');request.post( ...

最新文章

  1. QIIME 2教程. 28社区Community(2020.11)
  2. 对Erlang开发者的几点建议
  3. matlab画图(复数的直角坐标和极坐标)(-)
  4. 20220213-CTF MISC-a_good_idea(stegsolve工具的使用)-2017_Dating_in_Singapore
  5. 硬件信息修改大师_零成本学习之单片机硬件开发(1)
  6. 关于数组方面的算法分析
  7. html file 隐藏,input type=file /浏览时只显示指定文件类型(html5新特性)
  8. 清屏函数 mysql,mysql中的常用函数总结
  9. 【渗透测试案例】——Web前端的SQL注入是怎么回事?
  10. dwz框架---(2)表单回调函数
  11. 华南农业大学c语言上机实验答案,华南农业大学C语言上机实验答案.doc
  12. vue学习代码理解v-for数组遍历和对象遍历以及事件处理
  13. C#中Timer定时器的使用示例
  14. 2017年最受欢迎的15大Python库有哪些?
  15. java设计模式在java中的应用
  16. visio2013找到密钥以后但是未激活状态
  17. 随机数算法 java_最全的java随机数生成算法
  18. matlab牛头刨床矩阵,MATLAB牛头刨床分析程序-课程设计
  19. Java基础---整理1:JRE+进制+注释+关键字+标识符+变量
  20. SMT操作员是做什么的?工作职责?

热门文章

  1. centos安装盘ntfs_在CentOS下挂载NTFS格式U盘的方法
  2. 管理任务执行-有效执行
  3. 三十七 Python分布式爬虫打造搜索引擎Scrapy精讲—将bloomfilter(布隆过滤器)集成到scrapy-redis中...
  4. python SimpleHTTPServer 快速共享文件
  5. Log4j 2配置与IntelliJ IDEA控制台颜色
  6. 又发现一个visual studio 2015的坑啊。
  7. [学习笔记]批次需求计划系统-简要
  8. Ioc Autofac心得
  9. 数学图形之SineSurface与粽子曲面
  10. js导航条 二级滑动 模仿块级作用域