node.js中exports与module.exports的区别分析

前言

关于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以避免混淆。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/367384.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java反射教程

在本教程中,我主要编写一些示例来介绍Java反射可以做什么。 希望它可以给您这个概念的概述。 请留下您的评论以寻求建议。 什么是反射? 简而言之,反射是程序在运行时检查和修改对象的结构和行为的能力。 这种概念有时与内省混合在一起。 自…

NFS网络共享文件系统

1、nfs服务端配置操作 1.1 创建所需的共享目录--源 mkdir /data/rw #rw代表同步的数据可读可写 1.2 对共享目录进行授权 chown -R nfsnobody.nfsnobody /data/rw #非必需,根据业务需求 1.3 修改nfs服务配置文件 vim /etc/exports /data/rw 172.16.1.0/…

国家开放大学形成性考核 统一资料 参考试题

试卷代号:1174 水工钢筋混凝土结构(本)参考试题 一、选择题(每小题2分,共20分,在所列备选项中,选1项正确的或最好的作为答案,将选项号填入各题的括号中) 1.钢筋混凝土结…

两个向量之间的夹角公式_向量的内积

向量的内积也叫向量的数量积、点积。我们定义两个向量的内积是一个数: 其中 是这两个向量的夹角。 对于向量的内积,最重要的一个结论是: 定理1:两向量垂直的充分必要条件是它们的内积为 0,即 这个定理我们几乎不用证明了,因为从定义来看,如果两个向量都不零向量,则只能…

Go strings.Builder

Go strings.Builder 字符串拼接操作优化 最开始的时候,可能会使用如下的操作: package mainfunc main() {ss : []string{"sh","hn","test",}var str stringfor _, s : range ss {str s}print(str) }与许多支持string类型…

springcloud 入门 10 (eureka高可用)

eureka高可用: 说白了,就是加一个实例作为原实例的备份,然后一起对外提供服务。这样可以保证在一台机器宕机的时候,整个系统不会死掉。保证其继续对外服务。 eureka的集群化: 服务注册中心Eureka Server,是一个实例&am…

为什么REST如此重要

这篇文章致力于REST,一种塑造Web服务的体系结构风格,以及IT历史上最容易被误解的概念。 这篇文章针对的是那些正在设计Web服务api的人,他们并未完全了解REST的实际含义。 我想给你个主意。 这篇文章也发给了那些想知道REST意味着什么的人&…

string类有可以调换方向的函数吗_String类中常用的操作

一、获取:1、获取字符串的长度(注意是方法,不是跟数组的属性一样的)int length();1 public static void getLength(){2 String s "java01";3 int len s.length();4 System.out.println(len);5 }2、根据位置,获取该位置的那一个字符(只能是单…

你真的懂js获取可视区宽高吗

可能你会觉得获取可视区宽高不是很简单吗 原生js获取高度不就是就window.innerHeight一句话的事,可是真的这么简单吗 来看个测试页面,如果页面带有横向纵向的滚动条,我们打印出各个高度进行查看对比 顺便你也可以看看document.body和document.documentEl…

工作第七天

今天完成了一个简易的oauth服务器,通过login跳转到oauth保存uri和client_id,等待用户登录判断是否能get到user同时判断用户名和密码是否匹配,重定向到uri同时增加code参数,通过判断是否有code重定向回oauth,如果有code…

网上linux实验平台,Linux操作系统实验教程

第一部分 Linux操作系统基本原理.第1章 Linux操作系统简介1.1 Linux的渊源和发展简史1.2 Linux的基本特性1.3 Linux内核的开发模式与内核版本号1.4 Linux发行版介绍1.5 Linux内核源代码组织结构1.6 学习Linux的辅助软件介绍第2章 Linux的进程管理2.1 进程与进程描述符2.2 进程状…

詹金斯的Maven报告

代码质量是一个敏感的话题。 它会影响您的维护成本以及客户满意度。 更不用说您的开发人员使用代码的动力。 谁想要修复难看的代码,对吗? 讨论代码质量总是需要事实和数字! 因此,这是一个简短的教程,介绍如何创建一些…

python实现矩阵叉乘_矩阵乘法的纯Python实现 | 离开Python库!!

点击关注我哦一篇文章带你了解矩阵乘法的纯Python实现在《这篇文章》中,我们有简单提到“矩阵乘法”的相关知识,如果你不记得了,可以复习一下这张图片。想起来了没?本篇文章将深入探讨在没有机器学习库的情况下如何从零实现矩阵乘…

Github Actions:再次改变软件开发

本文转自 FEPulse 公众号(微信搜索 FEPulse,精选国内外最新前端资讯,为你把握前端脉搏)。 Github Actions 是 GitHub Universe 大会上发布的,被 Github 主管 Sam Lambert 称为“再次改变软件开发”的一款重磅功能&…

为别人软件加入广告或者密码(特别思路)

洪雨的的这款软件比较奇特,是忽然想到一个思路,然后实现了一下。 exe文件都有一个很有趣的地方,只要内部完整,就可以运行。比如一个exe文件,我们运行的时候,电脑知道他是exe所以可以直接运行。假如洪雨将它…

c free语言自定义函数,C 语言free函数的工作原理

今天在网上看到了这样一个问题,“如果malloc 了一块字符串的内存,然后,它改变了这个字符串的大小,问会不会有一部分内存没有被释放掉。”这个问题,以前的确没有仔细想过。当然,我觉得是肯定会释放掉的&…

Django 错误跳转页面

原网站:https://blog.csdn.net/goupper1991/article/details/50736826 django404,500错误自定义页面: 将 改为 1.修改settings文件DEBUG FalseALLOWED_HOSTS [127.0.0.1, localhost]或者ALLOWED_HOSTS [*]2.配置urls文件from django.conf.…

ElasticSearch-Hadoop:从Hadoop到ElasticSearch的产品视图计数索引和客户顶部搜索查询...

这篇文章涵盖了如何使用ElasticSearch-Hadoop从Hadoop系统读取数据并在ElasticSearch中对其进行索引。 它涵盖的功能是在最近n天中为每个客户的产品浏览量计数和热门搜索查询编制索引。 分析的数据可以进一步在网站上使用,以显示最近浏览过的客户,产品浏…

伸缩轨道_深度解析——伸缩喷漆房为什么这么受欢迎!

伸缩式喷漆房是一种环保喷漆设备,它可以在使用时,自动展开形成封闭或半封闭的环保喷漆房,不使用时收缩合拢到一处的特殊环保喷漆房设备,由于伸缩式喷漆房外观大方、简单实用且投资费用低,它在现代涂装应用中越发广泛。…

snippet,让你编码效率翻倍

为什么谈到Snippet 今天下午在用vscode做小程序的时候,发现很不方便,因为商店里提供的代码片段极为有限,而且平时几乎每天都需要用到代码片段,所以就在思考他们是怎么做到给别人提供代码的,我可以自定义代码片段吗。然…