我对这种关闭行为感到困惑。我已经阅读了几篇关于闭包的SO文章(包括this one)和MDN的文档,但是没有看到这种行为的解释。
在下面的代码示例中,我创建了一个包含变量cache
的闭包,一个修改它的函数preload
,以及一个记录其值的函数report
。它还将引用附加到传入的对象。
'use strict';
var o = {};
(function(obj) {
var cache = {'initialized': false};
function preload(assets, done) {
console.log('Preloading. Value of cache is', cache);
cache = {};
for (var i = 0; i < assets.length; i++) {
cache[assets[i]] = assets[i];
}
}
function report() {
console.log('Cache from inside is ', cache);
}
function get_cache() {
return cache;
}
obj.cache = cache;
obj.preload = preload;
obj.report = report;
} )(o);
// {initialized: false}, as expected
o.report();
// {initialized: false}, as expected
console.log('Cache from outside is ', o.cache);
// I expect this to change cache to {1:1, 2:2, 3:3}
o.preload([1, 2, 3]);
// {1:1, 2:2, 3:3}, as expected
o.report();
// {initialized: false}, NOT as expected. Why?
console.log('Cache from outside is ', o.cache);
我的期望是基于我的理解,当闭包将cache
附加到提供的obj
时,它会在闭包中分配对变量的引用。但我看到的行为表明,obj.cache
正在获取关闭cache
的副本。
此时是cache
创建的副本以及原因?
答案 0 :(得分:2)
当您在开头调用obj.cache = cache;
时,您obj.cache
指向cache
指向的同一对象(此对象:{'initialized': false}
)
稍后当您致电preload
时,您将变量cache
指向另一个新对象:cache = {};
。现在cache
变量指向一个全新的对象,而obj.cache
仍然指向在开头创建的旧对象。
这解释了为什么在闭包内的cache
上完成的所有日志都会记录新值,而记录obj.cache
仍然显示未更改的值。它们现在指向2个不同的对象,并且更改cache
现在指向的对象的内容对obj.cache
指向的原始对象没有影响。
答案 1 :(得分:0)
当您IIFE
被执行时,您已将cache
添加到obj.cache
,就是这样。 obj.cache
并未对您cache
中的IIFE
变量进行引用。但是,report
和preload
函数正在使用cache
中的IIFE
变量,即使它们是在创建它们的范围之外调用的。因此,IIFE
和obj.preload
函数保留了对obj.report
内部范围的引用(这是观察到闭包的地方),但不是obj.cache
。< / p>
有关如何观察和行使关闭的各种情况的更多详细信息,请查看此link。