我以为我理解了闭包,但突然之间的一些简单似乎并没有起作用。
我使用闭包创建了一个单例。这是一个非常缩小的版本:
Foobar = function() {
var data = null;
function init(obj) {
data = obj;
}
return {
init: init,
currentValue: data
}
}();
由于它是一个单身人士,我希望当我打电话给' init'功能,数据的价值'将在唯一存在的对象中进行更改,并且在使用' currentValue'的后续检索中该值仍然可用。
这是我的测试:
Foobar.init({id:3});
var test = Foobar.currentValue;
当我在Firefox(F12)中逐步执行此代码时,我可以看到是 - '数据'对于init函数是可见的,并且当我执行' init'时它正在改变该变量。但是,退出init函数并返回执行第二行测试后,var' test'被指定为null(创建单例时的原始值)而不是我传递给" init'的对象的副本。功能,正如我所料。
有人可以解决我的困惑吗?
答案 0 :(得分:1)
问题是在返回的对象中放置数据会在函数首次执行时保存值 - 这是null。
为了读取数据变量的当前值,currentValue必须是一个函数,如init。
Foobar = function() {
var data = null;
function init(obj) {
data = obj;
}
function currentValue() {
return data;
}
return {
init: init,
currentValue: currentValue
}
}();
console.log(Foobar);
Foobar.init({id:3});
var test = Foobar.currentValue();
console.log(Foobar,test);
答案 1 :(得分:1)
我认为你在这里混淆了两个不同的东西 - 也就是说,我认为你正在通过引用和#34; Javascript传递对象。和#34; Javascript关闭"困惑。
回答你的主要问题 - 问题是你在实例化时一次返回变量的值,然后再也不会。所以更新它不会改变任何东西。相反,如果您创建一个返回值的函数,您将看到它正在更新:
Foobar = function() {
var data = null;
function init(obj) {
data = obj;
}
function getCurrentValue() {
return data;
}
return {
init: init,
getCurrentValue: getCurrentValue
}
}();
Foobar.init({id:3});
console.log(Foobar.getCurrentValue());

现在,如果 data
被初始化为对象,而您的init
只是以某种方式扩展该对象,那么属性本身将在第一个示例中进行更新,因为它始终在整个生命周期中引用同一个对象:
Foobar = function() {
var data = {};
function init(obj) {
data.id = obj.id;
}
return {
init: init,
currentValue: data
}
}();
Foobar.init({id:3});
console.log(Foobar.currentValue);

答案 2 :(得分:1)
从
开始var Foobar = function () {...}();
该陈述可以分解为
var Foobar;
Foobar = function () {...}();
在第一行,Global范围注册了没有rhs引用的Foobar,因此在立即调用函数表达式(IIFE)之前的任何地方都没有定义Foobar。
在第二行,执行IIFE后,Foobar被分配给IIFE的返回对象,如下所示。
console.log(Foobar); // undefined
var Foobar = function () {...}();
console.log(Foobar); // Object {currentValue: null, init: function}
此时IIFE的返回对象可以显示为
然后,当 Foobar.init({id:3})时,执行。 Foobar的初始化将要求rhs参考,这恰好是IIFE的初始化。 init已关闭数据并最终将数据设置为 {id:3}
因此
var test = Foobar.currentValue;
显然仍然是 null 值作为其初始状态。
使它符合我们的期望。 anied提及至少有两种可能的解决方案。