再思考闭包

闭包指有权访问另外一个函数作用域的变量的函数,常见的方式是在一个函数中再创建一个函数。闭包中的作用域链是在本函数中的作用域向上一层的函数或者全局作用域连接。闭包可以访问作用域链连接的作用域中的变量和对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
var aMessage = "Hello World!";
var aFunction = function() {
var anotherMes = "Hello JS!";
//闭包
function() {
alert(anotherMes + "<br />");
alert(aMessage);
}
}
function createFunctions() {
var result = new Array();
for (var i=0;i<10;i++) {
//立即执行函数,所以得到返回并赋值于result[i]
result[i] = function(num){
return function() {
return num;
};
}(i);
}
return result;
}
//最后的结果是输出[0,1,2,3,4,5,6,7,8,9]
//但是如果直接返回i的话,由于作用域链的影响,for循环里面function(){return i;}并不会立即执行,
//而是在循环结束后,得到变量i的最后一个变量赋值10(i++,最后会自增1),所以最后得到的结果都是10;
function createFunctions() {
var result = new Array();
for (var i=0;i<10;i++) {
result[i] = function(){
return i;
};
}
return result;
}
//for循环中使用内置函数也是一样
for (var i=0;i<10;i++) {
setTimeout(function timer() {
console.log(i);
},i*1000);
}
//最终的结果是以每秒一次的频率输出10次10;循环中共用一个i变量,
//延迟函数的回调作用会在循环结束的时候才执行,最后i的值为10
for (var i=0;i<10;i++) {
setTimeout(function() {
console.log(i);
}(),i*1000);
}
//但是如果传递的函数是立即执行的话,得到(0-9)的正确输出,但是并没有计时器效果
for(var i = 0; i < 10; i++) {
(function(j) {
setTimeout(function timer() {
console.log(j);
},j*1000);
})(i);
}
//这段代码会得到正确的效果

利用闭包返回数组函数:

1
2
3
4
5
6
7
8
9
10
11
function makeClosures(arr, fn) {
var func = [];
for(var i=0;i<arr.length;i++) {
func.push(function(i) {
return function() {
return fn(arr[i]);
}
}(i));
}
return func;
}

坚持原创技术分享,您的支持将鼓励我继续创作!