关于闭包

本文是关于闭包的一些知识点总结

什么是闭包?

闭包就是指有权访问另一个函数作用域中的变量的函数

闭包的创建方式

创建闭包的常见方式:在一个函数内部创建另一个函数。

内部函数的作用域链包含外部函数的作用域,因此可以访问外部函数作用域中的变量

什么是作用域链?

本质上是一个指向变量对象的指针列表,它只引用但不实际包含变量对象。

闭包的副作用

(其中前两条由作用域链的配置机制引起)
由于闭包会携带包含他的函数的作用域,因此会比其他函数占用更多的内存;
只能取得包含函数中任何变量的最后一个值;

1
2
3
4
5
6
7
8
9
10
11
function createFunctions(){
var result = [];
for(var i = 0; i < 10; i ++){
result[i] = function(){
return i;
}
}
return result;
}
creatFunctions(); // [10,10,10,10,10,10,10,10,10,10]

原因:
每个函数的作用域链中都保存着 createFunctions() 函数的活动对象,所以他们引用的都是同一个变量 i 。
闭包保存的是变量对象,而不是某个特殊的变量;

解决办法:
通过创建另一个匿名函数,强制让闭包的行为符合预期;

1
2
3
4
5
6
7
8
9
10
11
12
13
function createFunctions(){
var result = [];
for(var i = 0; i < 10; i ++){
result[i] = function(num){
return function(){
return num;
}
}(i)
}
return result;
}
// 每个函数都会返回不同的索引值

以上代码中,没有直接把闭包赋给数组,而是定义了另一个匿名函数,并将立即执行匿名函数的结果赋给数组。这个匿名函数有一个参数 num ,也就是最终的函数要返回的值。在调用每个匿名函数时,就传入了变量 i。由于函数参数是按值传递的,所以就会将变量 i 的当前值赋值给参数 num。

在闭包中使用 this对象可能会导致一些问题:没有取得其包含作用域(外部作用域)的 this 对象;

1
2
3
4
5
6
7
8
9
10
var name = "The Window";
var obj = {
name: 'Bob',
getName: function(){
return function(){
return this.name;
}
}
};
alert(obj.getName()()); // "The Window"(在非严格模式下)

原因:
匿名函数的执行环境具有全局性,因此其 this 对象通常指向 window ;
每个函数在被调用时都会自动取得两个特殊变量(this 和 arguments),内部函数在搜索这两个变量时,只会搜索到其活动对象为止,永远不可能直接访问外部函数中的这两个变量;

解决办法:
把外部作用域中的 this 对象保存在一个闭包能够访问到的变量;

1
2
3
4
5
6
7
8
9
10
11
var name = "The Window";
var obj = {
name: 'Bob',
getName: function(){
var that = this;
return function(){
return that.name;
}
}
};
alert(obj.getName()()); // "Bob"

内存泄漏:如果闭包的作用域链中保存着一个 HTML 元素,那么就意味着该元素将无法被销毁;

1
2
3
4
5
6
7
function assignHandler(){
var element = document.getElementById('someElement');
element.onclick = function(){
alert('element.id');
};
}
// 只要匿名函数存在,element的引用次数至少是1,因此它所占用的内存就永远不会被回收。

将代码做如下改进,即可减少引用数,确保正常回收占用的内存:

1
2
3
4
5
6
7
8
function assignHandler(){
var element = document.getElementById('someElement');
var id = element.id;
element.onclick = function(){
alert(id);
};
element = null;
}

闭包的应用场景

参考博文【http://www.cnblogs.com/star-studio/archive/2011/06/22/2086493.html

您的支持将鼓励我继续创作!