闭包
javascript闭包产生的原因为函数内的子函数调用了父函数中定义的变量,形成了闭包。
- 第一种闭包形式
function f(){
var b = "b";
return function(){
return b;
}
}//函数中有一个局部变量,b在全局空间是不可见的,我们的f函数有一个返回值为一个函数,返回的这个函数如果我们赋值给一个全局变量,则可以生成一个可以访问f()私有空间的全局变量。
- 第二种形式闭包
var n;
function f(){
var b = "b";
n = function(){
return b;
}
}//n为全局变量,但在f函数内部,将新创建的内部函数赋值给n,所以n作用域为f和全局。
- 第三种形式闭包
function f(arg){
var n = function(){
return arg;
}
arg++;
return n;
}//因为函数参数通常视为自身局部变量,所以调用arg也就形成闭包。
- 循环中的闭包
function f(){
var a = [];
var i;
for(i = 0;i < 3; i++)
{
a[i] = function(){
return i;
}
}
return a;
}//猜猜这个函数运行结果什么。如何避免这种情况。
//修正方案
function f(){
var a = [];
var i;
for(i = 0;i < 3;i++)
{
a[i] = (function(i){
return function (){
return i;
}
})(i);
}
return a;
}
//解释:第一个之所以都为3是因为产生了闭包,而闭包中引用父元素的变量只有在调用时才会赋值,所以f()执行完,a[i](),并没有调用,i的值现在为3,所以调用时会全部为3。注意:子函数中变量时引用不是复制。
//修正方案使用立即执行函数,我们将i以参数传入,并且进行立即执行,所以每次i的值会保留,因为在传入参数的i是固定不变的。
//另一种修改方案
function f(){
function makeClosure(x){
return function(){
return x;
}
}
var a = [];
var i;
for(i = 0;i < 3;i++)
{
a[i] = makeClosure(i);
}
return a;
}//这种方法比较简单,不解释了。
//总结:循环闭包,使用场景为给一组元素同时绑定函数时偶尔遇到,最常见的是事件处理。遇到的肯定深有体会。