javascript中闭包的深入理解

作为面试必问的问题,对闭包必须进行深入研究。‘深入’二字请划重点。
最好是要理解到一定程度,什么程度呢?
就是你发现你的面试官原来对闭包的理解并不透彻,然后你为了给面试官个面子,不得不也装作一知半解的样子,这样你就牛逼了。
闭包学起来虽然可能对你很枯燥,但是一定要坚持,不能浮皮潦草。你要知道一个道理:水滴石穿。水能穿破坚硬的石头,何况是个闭包,前提是你还不比水弱。

概念

闭包:英文 closure。不知道谁翻译成了闭包,我个人认为不太合适 ,clousure是永久的意思。在编程中,可以理解为是一个永久存在内存中的变量。
不止javascript中存在闭包,在别的语言中也有。
javascript中如何产生闭包

1
2
3
4
5
6
7
8
9
function outer(){
var index=0;
var inner=function(){
index=1;
}
return inner;
}
var getData=outer()
console.dir(getData)

console.dir可以把对应数据结构打出来
可以看到scope(作用域)下,除了全局global,多了一个closure(闭包), 这就是闭包的形成。但是上面index必须被引用,如果不被inner引用,去了index=1,依旧不会形成闭包。闭包的形成依赖于外部函数变量的引用。

经典面试题

1
2
3
4
5
6
var el=document.getElementsByTagName('li');
for(var i=0;i<el.length;i++){
el[i].onclick =function(){
console.log(i)
}
}

上面打出来的并不是期望的值,
解决办法:闭包

1
2
3
4
5
6
7
8
9
var help=function(j){
return function(){
console.log(j)
}
}
var el=document.getElementsByTagName('li');
for(var i=0;i<el.length;i++){
el[i].onclick = help(i)
}

原理:因为遍历的时候变量i一直都会存在内存中。

闭包的使用场景

1
2
3
4
5
6
7
8
9
function callLater(a) {  
return function(){
a += 1;
console.log(a)
}
}

var funcRef = callLater(1);
hideMenu = setTimeout(funcRef, 5000);

闭包的优缺点:

优点: 防止变量跑到外层作用域中,发生命名冲突。
怎么理解呢?
1.比如本来我们想维持某个变量的状态,可能要通过全局变量去实现,但是有了闭包以后可以放在函数里面。
2.即使全局已经定义了一个跟闭包中相同的变量,全局的也不会收到影响。
缺点: 由于闭包中的变量会一直存在内存中,导致内存占用。在IE中会导致内存泄露(由于IE使用非原生javascript对象实现DOM对象),这是对浏览器很不友好的。
因此,不能滥用闭包。