[英]Understanding Node.js modules: multiple requires return the same object?
我有一个关于模块缓存的 node.js 文档的问题:
模块在第一次加载后被缓存。 这意味着(除其他外)每次调用 require('foo') 都会返回完全相同的对象,如果它解析为相同的文件。
多次调用 require('foo')可能不会导致模块代码被多次执行。 这是一个重要的特征。 有了它,可以返回“部分完成”的对象,从而允许加载传递依赖,即使它们会导致循环。
may
是什么意思?
我想知道 require 是否总是返回相同的对象。 所以,如果我需要在一个模块A app.js
和改变内部的出口对象app.js
需要在一个模块B(需要返回一个)和后app.js
这本身就需要模块A,我总是会得到该对象的修改版本,还是新版本?
// app.js
var a = require('./a');
a.b = 2;
console.log(a.b); //2
var b = require('./b');
console.log(b.b); //2
// a.js
exports.a = 1;
// b.js
module.exports = require('./a');
如果app.js
和b.js
都驻留在同一个项目中(并且在同一个目录中),那么它们都会收到相同的A
实例。 从node.js 文档:
... 每次调用
require('foo')
都会得到完全相同的对象返回,如果它解析为相同的文件。
当a.js
、 b.js
和app.js
在不同的 npm modules 中时,情况就不同了。 例如:
[APP] --> [A], [B]
[B] --> [A]
在这种情况下, require('a')
在app.js
将解析为一个不同的副本a.js
比require('a')
在b.js
,因此返回的不同实例A
。 有一篇博客文章更详细地描述了这种行为。
node.js 实现了某种缓存,可以在执行一些大型服务器项目时阻止节点读取文件 1000 次。
此缓存在require.cache
对象中列出。 我必须注意,这个对象是可读/可写的,它可以在不终止进程的情况下从缓存中删除文件。
http://nodejs.org/docs/latest/api/globals.html#require.cache
哦,忘记回答问题了。
修改导出的对象不会影响下一个模块加载。
这会造成很多麻烦... Require 总是返回一个新的对象实例,没有引用。
编辑文件并删除缓存确实会更改导出的对象
在做了一些测试之后,node.js 确实缓存了 module.exports。 修改require.cache[{module}].exports
最终得到一个新的、修改过的返回对象。
自从发布问题以来,文档已更新,以明确最初使用“可能”的原因。 它现在通过使事情变得明确来回答问题本身(我强调的是显示发生了什么变化):
模块在第一次加载后被缓存。 这意味着(除其他外)每次调用 require('foo') 都会返回完全相同的对象,如果它解析为相同的文件。
提供require.cache没有被修改,多次调用要求(“富”)将不会导致要多次执行该模块的代码。 这是一个重要的特征。 有了它,可以返回“部分完成”的对象,从而允许加载传递依赖,即使它们会导致循环。
就我所见,如果模块名称解析为先前加载的文件,则将返回缓存的模块,否则将单独加载新文件。
也就是说,缓存基于解析的实际文件名。 这是因为,通常情况下,同一包的不同版本可能安装在文件层次结构的不同级别,并且必须相应地加载。
我不确定的是,是否存在不受程序员控制或意识的缓存失效情况,这可能会导致意外地多次重新加载相同的包文件。
如果您希望require(x)
每次都返回一个新对象的原因仅仅是因为您直接修改了该对象 - 这是我遇到的一种情况 - 只需克隆它,然后只修改和使用克隆,如下所示:
var a = require('./a');
a = JSON.parse(JSON.stringify(a));
试试德雷克斯: https : //github.com/yuryb/drex
drex 正在监视模块的更新,并在更新后干净地重新需要该模块。 新代码被 require() ,就好像新代码是一个完全不同的模块,所以 require.cache 不是问题。
当您需要一个对象时,您需要的是它的引用地址,而通过两次请求该对象,您将获得相同的地址! 要拥有相同对象的副本,您应该复制(克隆)它。
var obj = require('./obj');
a = JSON.parse(JSON.stringify(obj));
b = JSON.parse(JSON.stringify(obj));
c = JSON.parse(JSON.stringify(obj));
克隆是通过多种方式完成的,你可以看到这个,了解更多信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.