JS闭包
javascript闭包 对我来说是一个难点,结合阮一峰老师,书籍以及同学的总结和建议写的这一篇笔记。在我看来 闭包 和 作用域 、垃圾回收机制 、函数嵌套 有关。
首先闭包为什么会产生,他到底是解决什么问题?
首先看一段代码:
var n=2;
function a (){
alert(n);
}
a() //此时返回2
结果为什么是2呢? ====> n为全局变量
再看一段代码:
function a(){
var n=2;
}
alert(n) //error
结果为什么是error呢? ===> n为局部变量
这个是 变量作用域 的问题:变量作用域分为 全局变量 和 局部变量(对其的理解在作用域及作用域链中)
那么你要读取函数的内部变量应该怎么解决?(1)
这是一个问题!
其次,看下面的代码:
var n=2;
function a (){
alert(n);
}
a() //此时返回2
a() //此时返回2
为什么得到的结果不是下面这样呢?
a() //此时返回2
a() //此时返回3
这个是javascript的垃圾回收机制问题:一个函数在执行开始的时候,会给其中的定义的变量划分内存空间保存,以备后面的语句所用,等到函数执行完毕后返回,这些变量就被认为是无用了,对应的内存空间就被回收了,再次执行时,所有的变量变为最初状态。
那么想要本次的执行结果是继承在上次的执行结果的基础上的呢?(即想让该变量长期的保存在内存中应该如何解决?)(2)
为了解决(1)(2)的两个问题所以引进了闭包。
所以引出闭包的作用:一个是读取函数内部变量,另一个是让变量的值始终保存在内存中。
既然闭包可以解决这两个问题,那么是怎样解决的呢?
function a(){
var n="Mozilla";
function displayName({
alert(n);
}
return displayName;
}
var myFunc=a();
myFunc();
这里用到的是 函数嵌套 :函数内部又嵌套了另一个函数,而内部函数又使用了外部函数的某些变量,这是垃圾回收机制就会出现问题。
此时javascript解释器在遇到函数定义的时候,会自动把函数和其他可能用到的变量一起保存起来,构成了闭包,只有当内部函数不被调用后,才销毁这个闭包。
其实在写闭包的时候也可以用到匿名函数。===>匿名函数:无需定义函数名的函数或者子程序。看下面的代码助于理解:
function a(){
var n = 'rain-man';
setTimeout(function(){ alert(n); } //这是一个匿名函数
, 2000);
}
a();
我用到的是ES6,所以上面的匿名函数就变为:
setTimeout( ()=>{ alert(n); } //这是一个匿名函数 , 2000);
当然闭包存在一些问题:
一个是因为闭包使函数中变量都保存在内存中,内存消耗很大。
另一个是在IE下可能导致内存泄露。(我理解的内存泄露是 页面跳转时变量不会释放,直到浏览器关闭才会释放。比较权威的解释是:一块被分配的内存,即不能使用,又不能被回收,直到浏览器进程结束)。
如何去注意点这些问题:
对于内存消耗大的问题,就要求我们不能滥用闭包,否则会造成网页的性能问题。
对于IE下的内存泄露问题:退出函数前,将不使用的局部变量全部删除。主要使用window.onunload.具体可以参照js内存泄露问题