我读了How do JavaScript closures work?个问题,并认为我终于理解了封闭。
特别是现在这一点非常混乱:
示例7
这个最后的例子表明每次调用都会为局部变量创建一个单独的闭包。每个函数声明没有一个闭包。每次调用函数都有一个闭包。 ..........................................
好的,所以示例7显示了这个例子:
function newClosure(someNum, someRef) {
// Local variables that end up within closure
var num = someNum;
var anArray = [1,2,3];
var ref = someRef;
return function(x) {
num += x;
anArray.push(num);
document.write('num: ' + num +
'; anArray: ' + anArray.toString() +
'; ref.someVar: ' + ref.someVar + "<br>");
}
}
obj = {someVar: 4};
fn1 = newClosure(4, obj);
fn2 = newClosure(5, obj);
fn1(1); // num: 5; anArray: 1,2,3,5; ref.someVar: 4;
fn2(1); // num: 6; anArray: 1,2,3,6; ref.someVar: 4;
obj.someVar++;
fn1(2); // num: 7; anArray: 1,2,3,5,7; ref.someVar: 5;
fn2(2); // num: 8; anArray: 1,2,3,6,8; ref.someVar: 5;
此示例适用于我。
所以我经历了一点,我真的不明白为什么这段代码不起作用(看起来它甚至没有在函数调用上创建一个新的闭包)
function createCounter(startValue){
var localCounter;
this.setCounter = function(firstValue) {
localCounter = firstValue;
}
this.getValue = function(){return localCounter;};
this.increment = function(){localCounter++;};
this.setCounter(startValue);
return this;
}
var Counter1 = createCounter(1);
document.write(Counter1.getValue()); //1
Counter1.increment();
var Counter1Value = Counter1.getValue(); // 2
var Counter0 = createCounter(0); //works as it should if i put a "new createCounter(0) here, but why?
document.write("<br >Counter 1 oldValue:" + Counter1Value); //2
document.write("<br >Counter 1 currentValue:" + Counter1.getValue()); //0 (why is the localvariable overwritten?)
document.write("<br >Counter 0 currentValue:" + Counter0.getValue()); // //0
为什么我需要添加“new”关键字来创建第二个闭包,为什么Counter1和Counter0都使用相同的localCounter变量?
答案 0 :(得分:0)
正如elclanrs所说,这完全是this
:
当您致电createCounter(1)
时,this
不变,很可能仍然是全球范围。给定document.write
,可以肯定地说全局范围是window
。因此,您创建window.setCounter
作为一个函数,将localCounter
(隐藏在闭包中的变量)和window.getValue
设置为读取此隐藏变量的函数;它会将localCounter
初始化为1
;然后返回window
并将其分配给Counter1
。
然后,Counter1.getValue()
调用window.getValue()
,返回1
。都好。与increment
相同。
但是,由于您始终在全局上下文中操作,因此当您执行createCounter(0)
时,覆盖 window.getValue
(和其他函数)与新闭包现在引用不同的隐藏localCounter
,此初始化为0
。由于Counter0
和Counter1
都指向相同的对象(即window
),因此Counter1.getValue()
和{{1}并不太牵强也应该返回相同的东西(假设它们都没有副作用)。
这会在Counter0.getValue()
关键字中发生巨大变化,这是JavaScript改变new
内容的几种方法之一。如果您执行this
和var Counter1 = new createCounter(1)
,则函数内的var Counter0 = new createCounter(0)
在两种情况下都是新对象; this
上的Counter1
与Counter0
有不同的闭包。
具体来说,new createCounter(0)
将执行类似此伪代码的操作:
var oldThis = this; // save current context
this = {}; // make a new object
createCounter(0); // initialize the new object
this = oldThis; // restore current context
所以你可以看到为什么值保持不同。