function Foo() {
var i = 0;
return function() {
console.log(i++);
}
}
var f1 = Foo(),
f2 = Foo();
f1(); // 0
f1(); // 1
f2(); // 0
很疑惑f1和f2不是公用Foo的i吗?那f2()应该是2啊?
求大神解释一下
function Foo() {
var i = 0;
return function() {
console.log(i++);
}
}
var f1 = Foo(),
f2 = Foo();
f1(); // 0
f1(); // 1
f2(); // 0
很疑惑f1和f2不是公用Foo的i吗?那f2()应该是2啊?
求大神解释一下
楼上的各位都在关注闭包,其实题主更应该关注的是这个变量i,因为你每执行这个函数,变量i就重新初始化。
正应为重新执行函数以后,才得到的楼主的答案。
继续回到题主的问题上,如果想让i不被重新执行函数的时候初始化,该怎么办?很简单。
1. 将变量i变成相对于函数外全局变量,也就是如下这样:
var i = 0;
function Foo() {
return function() {
console.log(i++);
}
}
var f1 = Foo(),
f2 = Foo();
f1(); // 0
f1(); // 1
f2(); // 2
2 不用var声明,不过这样是不推荐的,容易造成变量混乱。
function Foo() {
i = 0;
return function() {
console.log(i++);
}
}
var f1 = Foo(),
f2 = Foo();
f1(); // 0
f1(); // 1
f2(); // 2
javascript
var f1 = Foo(); //执行一次foo(),var i = 0; var f2 = Foo(); //重新执行一次foo(),var i = 0;
所以f1
,f2
之间的i
都是互不关联的。
如果
javascript
var i=0 function Foo() { return function() { console.log(i++); } }
把i
定义在函数外部,那么f1
,f2
之间的i
就会有关联,
或者
javascript
var f1=Foo(); f2 = f1;
这样f1
,f2
都是指向同一个引用,i
也会是相同的。
先说句题外话,闭包这个名字取的就是错的,如果学过离散数学或者SICP的话,就知道闭包是离散数学中的概念。我们平时说的“闭包”在SICP中被称为“自由变量”。不过大家都这么叫,其实也无所谓了。
我打个比方,有一家机器人餐厅,为了保证服务质量是一致的,每次客人进来时,会现场初始化一台机器人服务员为该客人服务,客人离场后销毁该机器人。后来餐厅开放了新服务:如果客人很喜欢这次的机器人的话,可以申请保留下来并得到一个机器人所有权凭证,下次来餐厅时出示这个凭证就可以由这个机器人为他服务,这个机器人也不会再因为客人离场而自动被销毁。
上面这个比方临时想的,可能不是很恰当,但是你应该能看出来,“闭包”里的变量和“机器人餐厅”里的机器人是对应的,返回的闭包函数和凭证时一一对应的。我觉得这就是为什么SICP中称这种机制里的变量为“自由变量”,因为这个变量不再受常规的变量生存周期制约,变得更加灵活,更加“自由”。
回到你的问题。Foo、f1和f2都是进入“机器人餐厅”的方法,区别在于,Foo是不出示凭证的,而f1、和f2是出示不同凭证的。
f1
和f2
不是公用foo
的。都是拷贝一份foo
,然后赋值给他们。所以他们里面的i
值是没有关联的。下面代码修改一下就是你要的结果:
var f1 = fn(),
f2 = f1;
10 回答11.2k 阅读
5 回答4.8k 阅读✓ 已解决
4 回答3.1k 阅读✓ 已解决
2 回答2.7k 阅读✓ 已解决
3 回答2.3k 阅读✓ 已解决
3 回答2.2k 阅读✓ 已解决
2 回答2.6k 阅读✓ 已解决
类似的闭包问题
你可以看看这个问题,还有评论里的扩展问题,和你这个很类似。