Javascript 闭包不适用于返回的函数
Javascript Closures with doesn't work with returned function
我阅读了 How do JavaScript closures work? 问题并认为我终于理解了闭包。
特别是这一点现在很迷惑:
Example 7
This final example shows that each call creates a separate closure for the local variables. There is not a single closure per function declaration. There is a closure for each call to a function.
..........................................
好的,所以示例 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 变量?
正如 elclanrs 所说,一切都是关于 this
:
当您调用 createCounter(1)
时,this
没有变化,很可能仍然是全局范围。鉴于 document.write
,可以安全地说全局范围是 window
。因此,您将 window.setCounter
创建为一个函数,它将设置 localCounter
,一个隐藏在闭包中的变量,并将 window.getValue
设置为读取此隐藏变量的函数;它将 localCounter
初始化为 1
;然后它 returns window
并将其分配给 Counter1
.
然后,Counter1.getValue()
调用 window.getValue()
,return 调用 1
。都好。与 increment
.
相同
但是,由于您一直在全局上下文中进行操作,因此当您执行 createCounter(0)
时,您正在 覆盖 window.getValue
(以及其他函数) 带有一个 new 闭包,现在引用一个 different 隐藏 localCounter
,这个被初始化为 0
。由于 Counter0
和 Counter1
都指向 相同的 对象(即 window
),因此 Counter1.getValue()
和Counter0.getValue()
也应该 return 同样的事情(假设它们都没有副作用)。
使用 new
关键字,这会发生巨大变化,这是 JavaScript 中改变 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
因此您可以了解为什么值保持不同。
我阅读了 How do JavaScript closures work? 问题并认为我终于理解了闭包。
特别是这一点现在很迷惑:
Example 7
This final example shows that each call creates a separate closure for the local variables. There is not a single closure per function declaration. There is a closure for each call to a function. ..........................................
好的,所以示例 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 变量?
正如 elclanrs 所说,一切都是关于 this
:
当您调用 createCounter(1)
时,this
没有变化,很可能仍然是全局范围。鉴于 document.write
,可以安全地说全局范围是 window
。因此,您将 window.setCounter
创建为一个函数,它将设置 localCounter
,一个隐藏在闭包中的变量,并将 window.getValue
设置为读取此隐藏变量的函数;它将 localCounter
初始化为 1
;然后它 returns window
并将其分配给 Counter1
.
然后,Counter1.getValue()
调用 window.getValue()
,return 调用 1
。都好。与 increment
.
但是,由于您一直在全局上下文中进行操作,因此当您执行 createCounter(0)
时,您正在 覆盖 window.getValue
(以及其他函数) 带有一个 new 闭包,现在引用一个 different 隐藏 localCounter
,这个被初始化为 0
。由于 Counter0
和 Counter1
都指向 相同的 对象(即 window
),因此 Counter1.getValue()
和Counter0.getValue()
也应该 return 同样的事情(假设它们都没有副作用)。
使用 new
关键字,这会发生巨大变化,这是 JavaScript 中改变 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
因此您可以了解为什么值保持不同。