您的位置:首页 > Web前端 > JavaScript

javascript 函数初探 (六)--- 闭包初探#4

2016-08-27 16:10 316 查看
环中的闭包:

让我们来看一下一个会循环三次的操作,她在每次迭代中都会创建一个返回当前序列号的新函数,该函数会被添加到一个数组中,并最终返回:

function F(){
var arr = [], i;
for(i=0; i<3; i++){
arr[i] = function(){
return i;
}
}
return arr;
}

var arr = F();

arr[0](); // 3
arr[1](); // 3
arr[2](); // 3


显然这不是我们想要的结果。为啥呢?

原来我们在三次循环中创建了三个闭包,而他们最终都指向了一个共同的局部变量i。但是闭包不会记录她们的值(上文说过),她们有的只不过是相关域在创建时的一个链接(引用)。

在这个例子中,变量i恰巧存在于定义这三个函数作用域中。对于这三个函数而言,当她们要获取某个变量时,她会从其所在的域开始逐级向上找那个距离最近的i,由于循环结束时i值为3,所以这三个值同时指向了这一个i值。

如何纠正这种行为呢?答案是换一种闭包形式:

function F(){
var arr = [], i;
for(i=0; i<3; i++){
arr[i] = (function(x){
return function(){
return x;
}
})(i);
}
return arr;
}

var arr = F();
arr[0](); // 0
arr[1](); // 1
arr[2](); // 2


这里我们不再直接创建一个返回i的函数了,而是将i传递给了另一个即时函数,在即使函数中i就被赋值给了局部变量x,这样一来每次循环都会有不同作用域的局部变量x,那么以来每个函数中的x值都会不同了。

或者我们可以来个正常点的:

function F(){
fucntion her(x){
return function(){
return x;
};
};
var arr = [], i;
for(i=0; i<3; i++){
arr[i] = her(i);
};
return arr;
}


目的是为了使中间函数将i值本地化。

假如我们不想把一个变量暴露到全局作用域中,因为这样的话,其他代码就会有修改她们的可能,所以我们会把这个变量保护到相关函数内部,然后提供两个额外的函数, getter(),setter()。一个用来获取变量,另一个用来对变量赋值。

var gets, sets;
(function(){
var a = 0;
getValue = function(){
return a;
}
setValue = function(v){
if(typeof v === 'number'){
a = v
}
}
})();

setValue(1);
getValue(); // 1


下面一些章节我们来探讨一下对象,敬请期待。。。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: