【JS】这段代码不是很理解?为什么最后输出10
javascript
function constfuncs() {
var funcs = [];
for (var i = 0; i < 10; i++) {
funcs[i] = function () {
return i;
}
}
return funcs;
}
var funcs = constfuncs();
alert(funcs[1]());
funcs[1]() 这个是什么意思?
回答
如果你想得到你“想象中”的结果,需要用闭包。
这题里,你的每一个funcs[i]都声明了一个函数,但是函数都没有被立刻执行,而是排进了队列。
但是你的for循环是一直在执行的,等10个函数声明完毕,i也走完了,就是说i现在的值是10。
这时,你调用funcs[1]()
去执行你之前声明的函数,因为现在i是10,所以理所应当的返回10。
如果你想得到“正确”的结果,需要用闭包改写:
function constfuncs() { var funcs = [];
for (var i = 0; i < 10; i++) {
funcs[i] = (function () {
return i;
}(i))
}
return funcs;
}
var funcs = constfuncs();
console.log(funcs[1]);
用闭包保存i,这样你最后返回的值才会是你输入的值i。
这是个闭包的问题。funcs[1]
是一个函数,返回的值是 i。funcs[1]()
就是运行这个函数。
对于外部 constfuncs
来说,下面这个就是个闭包。
javascript
funcs[i] = function() {
return i;
}
《JS高级程序设计》p.181 就是这个例子。
闭包保存的是整个对象,而不是特殊变量
每个funcs[n]里面引用的都同一个变量 i ,所以最后的返回值是一样的。
我把题中的函数改了改,为了方便显示,i 就改成了3。楼主看图感受下,应该就明白了。
首先,
funcs是生成了10个function对象的数组,每个节点都是一个
javascript
function () {
return i
}
但这里有个bug,这里的i其实都是引用了var i;所以闭包里面i都是指向同一个i;
解决的话,需要一个自执行的方案,
javascript
function constfuncs() {var funcs = [];
for (var i = 0; i < 10; i++) {
funcs[i] = (function (e) {
return e;
})(i);
}
return funcs;
}
var funcs = constfuncs();
alert(funcs[1]());
我知道 let
也能解决。
javascript
for (let i = 0; i = 0; i < 10; i++) {
...
}
也能解决,不知道是不是所有浏览器都支持
回答的瞬间就有三个答案了
function constfuncs() { var funcs = [];
for (var i = 0; i < 10; i++) {
funcs[i] = (function (i) {
return function(){
return i;
};
}(i))
}
return funcs;
}
var funcs = constfuncs();
console.log(funcs[1]());
闭包内捕获的变量是一个引用,而不是当时变量值的快照,相反的,函数参数中的参数传递传递的是变量的值。题目中的源代码里,闭包捕获到的是变量i的引用,始终指向变量i,i的值在循环式的最后变为了10,所以所有函数的返回值均为10。
以下代码就是一个返回当时变量i的值的快照的形式。在函数createFunc的参数传递中对变量i的值进行了拷贝。
function constfuncs() { var funcs = [];
for (var i = 0; i < 10; i++) {
function createFunc(i) {
return function() {
return i;
};
}
funcs[i] = createFunc(i);
}
return funcs;
}
var funcs = constfuncs();
alert(funcs[1]());
这就是个闭包呀,犀牛书上的例子。
var funcs = constfuncs();
constfuncs()运行这个函数,并将return结果返回给funcs。
过程:1. 新建数组,同时for循环生成一个函数数组。每个函数数组中属性都是function(){return i};
2. for循环结束。此时i=10.
3. rerurn 这个函数数组给funcs。此时funcs是一个函数数组。
注意:第一步中,循环只是把这些函数function(){return i}放进数组中,这些函数本身是没有运行的。
第三步是funcs是这个函数数组的外部引用,所以,constfuncs这个函数的作用域对象,没有当做垃圾被回收。
alert(funcs[1]());
过程: 1.运行这个函数数组中第二个函数, 此时function(){return i}
2.在运行function(){return i}时。i的循环已经结束了。而且i的值为10.所以此时运行结果就是返回一个数字10。
funcs是一个数组,数组元素个数为10个,每个元素都是函数
function () { return i; //for循环完结后,i的值为10.
}
funcs[1]表示第一个元素,即以上的函数
funcs[1]()表示执行函数。函数返回值为10,所以输出10
考察了闭包的概念
内部funcs[i]形成闭包,与循环构成异步,循环瞬间执行完,内部的闭包待循环执行完之后才拿到值,当然就是10咯
以上是 【JS】这段代码不是很理解?为什么最后输出10 的全部内容, 来源链接: utcz.com/a/87125.html