最近开始学习js,都说js是javascript中很NB的东西,很难理解,我觉得这个应该没那么难,怕的是你看错了书,被概念给忽悠了。
看代码,只是对内部函数后面多了一个(i), 该语句的作用是调用匿名函数表达式,因此,每次for循环,res[i]就调用一次匿名表达式,得到实际的值,随后返回时,alert(o)结果为:
首先说下闭包的概念:闭包就是函数内部定义个函数,因而内部函数可以访问外部函数的变量的引用,记住是引用.
我觉得javascript提出闭包的概念是因为想让调用一个函数后,还能访问函数内部的变量,所以闭包就产生了。
看一个例子:
function out(){
var res = new Array();
for (var i = 0; i < 10; i++){
res[i] = function(){
return i;
};
}
return res;
}
var o = out();
alert(o);
alert(o[0]()); // 10
解释: 这里定义了一个函数out,out函数内部定义了一个数组res, for循环为数组的每个值进行赋值,注意一点,赋值的语句是一个函数,最后返回res
当调用alert(o);时,结果如下:
function (){ return i; },function (){ return i; },function (){ return i; },function (){ return i; },function (){ return i; },function (){ return i; },function (){ return i; },function (){ return i; },function (){ return i; },function (){ return i; }
你没看错,就是10个函数的集合,而不是0,1,2,3,4,5,6,7,8,9;原因是每个赋值语句返回的是一个匿名函数表达式,而匿名函数表达式必须要调用时才返回数据,否则,其存储的实际是一个函数对象。
当调用alert(o[0]());时返回的值是10,这有点惊讶,感觉应该是0,原因是:
当out()函数返回后,out函数已经没用了,而out函数的内部的所有变量都将作为内部函数的外部引用变量,所以,每个函数都保存了这些变量的引用,当一个变量变化时,所有函数读取的都是变量的引用,所以最终都是10。
也可以从另一个角度理解,对于内部函数来说,其外部函数的变量相对于函数本身就是全局变量,全局变量的特征就是所有对象共享,因此当有一个对象对全局变量改变时,其他所有对该变量的引用都改变了。
上面出现的那个问题时返回数组时才调用函数导致延迟了读取变量的值,修改一下上面的代码,就能得到理想的结果了:
function out(){
var res = new Array();
for (var i = 0; i < 10; i++){
res[i] = function(){
return i;
}(i);
}
return res;
}
var o = out();
alert(o);
alert(o[0]());//undefined
看代码,只是对内部函数后面多了一个(i), 该语句的作用是调用匿名函数表达式,因此,每次for循环,res[i]就调用一次匿名表达式,得到实际的值,随后返回时,alert(o)结果为:
0,1,2,3,4,5,6,7,8,9;而alert(o[0]())返回错误 Number is not a function错误。
说到底,感觉只用认真的分析返回的是值还是对象就能解决这个问题了,因为值是不变的 ,对象是对其他对象的引用,当有对其他对象改变时,该对象就变了。