<!DOCTYPE html>
<html>
<body>
<p>Counting with a local variable.</p>
<button type="button" onclick="myFunction()">Count!</button>
<p id="demo"></p>
<script>
function Add(x) {
this.counter = x;
return function () {return this.counter += 1;}
};
var add = Add(0);
当我用"var add = Add(0);"
替换"var add = new Add(0)"
时,输出显示为“NaN”。为什么?以及这实际上是如何运作的?
function myFunction(){
document.getElementById("demo").innerHTML = add();
for each click 1, 2, 3 ....
}
</script>
</body>
</html>
答案 0 :(得分:2)
new
用于根据现有定义(存储在Add
中)创建新实例。您没有生成实例,而是返回一个函数,因此它无法按预期运行。
此表格应该有效:
function Add(x) {
this.counter = x;
this.addOne = function() {
return this.counter += 1;
}
}
var add = new Add(0);
function myFunction() {
document.getElementById("demo").innerHTML = add.addOne();
}
关于您的代码返回NaN
的原因的问题,让我们来看看您在做什么:
function Add(x) {
this.counter = x;
return function () {return this.counter += 1;}
};
var add = new Add(0);
function myFunction(){
document.getElementById("demo").innerHTML = add();
}
在此声明变量add
并使用new Add(0)
对其进行初始化。首先,Add
函数在其自己的作用域中声明一个名为counter
的属性,并通过名为x
的参数(在本例中为0)为其分配值。然后,它返回一个函数。然后它退出,不再需要,并且是垃圾收集。分配给counter
属性的值将被丢弃,因为它所附加的this
已超出范围。
您现在有add
作为指向函数的指针。它没有名为counter
的属性。当您调用add()
函数时,它会尝试将{1}添加到this.counter
。由于未定义this.counter
,因此它自动具有值undefined
。
如果您尝试向undefined
添加号码,则会获得NaN
。由于这是在return
语句中发生的,因此会返回NaN
。
答案 1 :(得分:2)
Add(0)
和new Add(0)
之间的区别在于第一个在window
上下文中调用该函数。而第二个在新的{}
上下文中调用该函数。但是,匿名函数中的this
不会引用新的{}
上下文,因为它是在window
上下文中调用的,因为add()
与window.add()
相同}}
出于调试目的,请尝试将一些警报或console.log添加到您的函数中:
function Add(x) {
alert('The context Add was called with is: '+this);
this.counter = x;
return function () {
alert('The context the anonymous function was called with is '+this);
return this.counter += 1;}
};
然后你会看到this
指向的内容。如果window.counter
未定义,则您获得NaN,因为return this.counter += 1;
正在向undefined
添加1,从而导致NaN
。
就解决方案而言,一个选项是bind
函数到你想要它的上下文:
http://jsfiddle.net/eu9r8pau/4/
另一个选择是通过存储对此的引用来利用闭包:
http://jsfiddle.net/eu9r8pau/5/
您还可以将代码重写为更简单的代码:
http://jsfiddle.net/eu9r8pau/6/
答案 2 :(得分:0)
为Dan Lowe的帖子和解释添加另一个变体,这一次关于OP的例子的标题谈论一个局部变量,我认为这是一个私有变量:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<p>Counting with a local variable.</p>
<button type="button" onclick="myFunction()">Count!</button>
<p id="demo"></p>
<script>
function Add(x) {
var counter = x;
return function () {return counter += 1;}
};
var add = new Add(0);
function myFunction(){
document.getElementById("demo").innerHTML = add();
}
</script>
</body>
</html>
这是,我认为一个闭包的经典例子。变量counter
保留在函数Add
的范围内,只有增加它的函数才是公共的。
您可以根据需要使用尽可能多的Add
实例,并拥有尽可能多的独立计数器。例如,添加另一个从100开始:
var bdd = new Add(100);
function myFunction(){
document.getElementById("demo").innerHTML = add() + "<br />" + bdd();
}
此页右侧的“相关”列有一个很好的explanation闭包,请看一下。