当前位置: 首页 > 后端技术 > Node.js

require的时候,你真的了解exports和module.exports的区别吗?

时间:2023-04-03 20:50:07 Node.js

面试会问你了解require的运行机制和缓存策略吗?是否需要同步或异步加载模块?谈谈你对exports和module.exports的区别的理解?require加载模块时到底加载了什么?require提到exports和module.exports我们不得不提到require关键字。大家都知道Node.js遵循CommonJS规范,使用require关键字来加载模块。require重复引入问题问:不知道小伙伴在使用require导入模块的时候有没有什么关系。多个代码文件中多次引入同一个模块会不会造成重复?因为在C++中通常会使用#IFNDEF等关键字来避免重复引入文件,而在Node.js中则不需要关心这个,因为Node.js默认从缓存中加载模块。一个模块加载一次后,会在缓存中维护一个副本。如果一个模块被重复加载,缓存中的副本将被直接提取,这意味着每个模块在任何时候都只有一个实例在缓存中。加载模块时需要同步还是异步?先回答问题,同步!但是如果面试官问你为什么是同步的还是异步的?其实这个答案并不是固定的,但是小伙伴们可以通过这几个方面来向面试官说明。一个是公共依赖的模块,当然是想一次性加载,而同步好的模块数量往往是有限的,而Node.js会在require的时候自动缓存加载的模块,所有的访问都是本地的文件,产生的IO开销几乎可以忽略不计。require()的缓存策略Node.js会自动缓存通过require导入的文件,这样下次导入就不需要经过文件系统,直接从缓存中读取。但是这种缓存方式是通过文件路径来定位的。即使两个相同的文件位于不同的路径,缓存中也会保留两个副本。当前在缓存中的所有文件都可以通过console.log(require.cache)获取。exports和module.exports的区别在于当一个js文件启动,节点执行一个文件时,文件中会生成一个exports和module对象,module有一个exports属性。它们之间的关系如下图所示,它们都指向一个{}内存区域。exports=module.exports={};看一张图更清楚地理解这一点:require()加载模块require()加载模块时,我们看一个示例代码//koala.jsleta='程序员的成长指南';console.log(module.exports);//可以打印的结果是:{}console.log(exports);//可以打印的结果是:{}exports.a='程序员的成长指南北';//这里的辛苦有助于将module.exports的内容改为{a:'程序员的成长指南'}exports='指向其他内存区域';//在这里,指向导出//test。jsconsta=require('/koala');console.log(a)//printas{a:'程序员成长指南北'}看上面代码的打印结果,应该可以得出这样的结论:requireexports的内容是module.exports指向的内存块的内容,不是exports。简而言之,它们的区别在于exports只是对module.exports的引用,用于辅助后者添加内容。借助于内存指向更好理解。官网上的一个例子看看官方文档中exports的应用我们经常看到这样的写法:exports=module.exports=something上面的代码相当于:module.exports=somethingsexports=module.exports原理是很简单,就是当module.exports指向一个新的对象时,exports断开对module.exports的引用,然后通过exports=module.exports让exports重新指向module.exports。一些使用建议:在使用的??时候,建议大家使用module.exports(根据下面的例子),Node.js认为每个文件都是一个独立的模块。如果你的包有两个文件,比如“a.js”和“b.js”,那么“b.js”想要使用“a.js”的功能,“a.js”必须传递给导出对象添加property来暴露这些函数://a.jsexports.verifyPassword=function(user,password,done){...}一旦这样做了,每个需要“a.js”的人都会得到一个带有“verifyPassword”的函数的对象properties://b.jsrequire('a.js')//{verifyPassword:function(user,password,done){...}}但是,如果我们想直接暴露这个函数,而不是把它当作某些对象的属性?我们可以覆盖exports以达到目的,但我们不能将其视为全局变量://a.jsmodule.exports=function(user,password,done){...}请注意,我们将“exports”用作模块对象的属性。“module.exports”和“exports”之间的区别很重要,并且经常让Node.js新手感到困惑。加入我们,一起学习!节点学习交流群交流群成员超过100人,无法自动入群。请加群助手微信号:[coder_qi]备注节点,会自动拉你入群。