我以为我理解了闭包,但突然间一些简单的东西似乎不起作用。
我使用闭包创建了一个单例。这是一个非常精简的版本:
Foobar = function() {
var data = null;
function init(obj) {
data = obj;
}
return {
init: init,
currentValue: data
}
}();
由于它是一个单例,我希望当我调用“init”函数时,“data”的值将在唯一存在的对象中更改,并且该值在后续检索中仍然可用'当前值'。
这是我的测试:
Foobar.init({id:3});
var test = Foobar.currentValue;
当我在 Firefox (F12) 中单步执行此代码时,我可以看到是的 - 'data' 对 init 函数可见,并且当我执行 'init' 时它正在更改该变量。但是,退出 init 函数并返回执行测试的第二行后,var 'test' 被分配为 null(创建单例时的原始值),而不是我传递给 'init' 函数的对象的副本,正如我所料。
有人可以解答我的困惑吗?
最佳答案
从
开始var Foobar = function () {...}();
该语句可以分解为
var Foobar;
Foobar = function () {...}();
在第一行,全局范围注册了 Foobar,没有 rhs 引用,因此 Foobar 在立即调用函数表达式 (IIFE) 之前的任何位置都未定义。
在第二行,执行 IIFE 后,Foobar 被分配给 IIFE 返回的对象,如下所示。
console.log(Foobar); // undefined
var Foobar = function () {...}();
console.log(Foobar); // Object {currentValue: null, init: function}
此时 IIFE 返回的对象可以可视化为
然后,当执行Foobar.init({id:3});时。 Foobar 的 init 会请求 rhs 引用,而该引用恰好是 IIFE 的 init。 init 关闭了数据并最终将 data 设置为 {id:3}
因此
var test = Foobar.currentValue;
显然其初始状态仍然是一个null值。
使其达到我们的期望。这里至少有两种可能的解决方案:anied曾提到过。
- 在 IIFE 中创建另一个带有数据闭包的函数,以便 找回它们。
- IIFE 的 init 不是将数据分配给新对象,而是直接初始化 操纵同一个对象本身。
关于javascript - 关闭不保持状态变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43302201/