js之闭包

来源:互联网 发布:如何免费申请阿里云 编辑:程序博客网 时间:2024/06/05 20:19

首先闭包涉及到的知识点有:函数基本概念、作用域链、函数生命周期。
请在学好上述知识点后阅读此文章。
我先给出闭包的概念吧:闭包是指有权访问另一个函数作用域中变量的函数。

首先,上代码:
function foo(){
var a=1;
return function(){
return a+1;
};
}
foo();// 2
现在思考一下,外部函数为什么能够访问内部的局部变量a?
因为内部匿名函数的作用域链包含外部函数foo()的作用域。要了解其中的细节,必须理解函数被调用的时候发生了什么。

先上图:
这里写图片描述

1.首先,foo()函数在全局环境中调用,并且创建了自己的执行环境,所以foo()的作用域链有两个作用域,一个指向全局,另一个是其函数内部作用域,并且指向各自的作用域创建活动对象(如图)
2.当执行内部匿名函数时,同样也会创建匿名函数的执行环境,所以匿名函数的作用域链有3个作用域:全局、foo()的作用域、匿名函数的作用域。并且指向各自的作用域创建活动对象(如图)
3.作用域按顺序入栈,首先会先处理作用域链栈顶的作用域。
4.处理完成后,依次从栈里弹出,并且销毁其作用域的活动对象。

好了,问题就在这,请问当foo()函数执行完毕后,其活动对象会被销毁吗?
答案是不会的,foo()函数执行完毕后,其执行环境会被销毁,作用域也被销毁,但活动对象不会,因为匿名函数在返回的同时匿名函数的作用域链还在引用全局活动对象和foo()的活动对象,知道匿名函数的作用域链销毁后,全局活动对象和foo()的活动对象才会被销毁。而那个匿名函数的活动对象,就是闭包。

从中可以看出,即使外部函数执行完毕,但其活动对象仍然未被销毁,其作用域中的变量的值仍然会保留着。这也是以下代码会连续输出5个5的原因:
function a(){
for(var i=0;i<5;i++){
setTimeout(function(){
console.log(i);
},1000);
}
}
要想阻止此现象,只需强行让闭包销毁即可,如下:
function a(){
for(var i=0;i<5;i++){
setTimeout((function(){
console.log(i);
})(i),1000);
}
}
在创建匿名函数的同时,立即执行它使其销毁即可。

以上是我对闭包的了解,希望路过的大佬能给点意见,留下评论,谢谢!

2 0
原创粉丝点击