1、什么是闭包?
简单来说,闭包就是在一个定义在函数内部的函数,或者将一个函数内部的函数保存在外部,由于在js 中存在作用域的问题,所以在函数内部定义的变量在外部是无法直接获取的。而闭包就是函数内部和外部的桥梁,这样在函数外部接可以得到函数内部的值。并且闭包可以实现函数属性和方法的私有化。
我们看看下面的一段代码:
function a() {
function b() {
var bbb = 234;
document.write(aaa);
}
var aaa = 123;
return b;
}
var glob = 100;
var demo = a();
demo();
上面的代码中简单的运用了闭包,我们来分析一下这段代码
根据上图我们可以看出a函数被执行时,我们根据前面讲到的JavaScript的作用域的知识,在a函数对象的属性[[scope]]的作用域连scope chain有两个对象,分别是AO 和 GO对象,也就是活动对象和全局对象。在a 函数执行完成之后,b函数被定义了,而且b函数被保存在了外部,通过变量demo接收b函数。所以就构成了闭包。
2、闭包有什么危害?
我们说了,闭包是在一个定义在函数内部的函数,或者将一个函数内部的函数保存在外部。在这个过程中其实是将内部变量保存在了内存中,如果长时间不清楚的话会造成内存泄漏,影响程序性能。
3、如何解决闭包带来的危害?
因为闭包会将内部变量储存在内存中,如果长时间不清除的话会造成内存泄漏的问题,影响程序的性能。解决方法:对于不使 用的变量及时的清除。
4、关于JavaScript中的闭包及应用场景
-
通过闭包可以实现函数内的局部变量的累加
function fn(){
var num=100;
return function(){
num++;
return num;
}
}
var b=fn();//获得函数
//你会发现局部变量num并没有在内存当中消失
console.log(b());//调用匿名函数
console.log(b());//第二次调用匿名函
由于在闭包所在的作用域返回的局部变量不会被销毁,所以会占用内存。过度的使用闭包会迫使性能下降,因此建议大家在有必要的情况下再使用闭包。
5、闭包常见的作用
-
模拟块级作用域(匿名自执行函数)
if(){}for(){}等没有作用域,所以在其块内声明的变量,在外部是可以使用的。
//javaScript没有块级作用域的概念
function fn(num){
for(var i=0;i<num;i++){}
console.log(i);//在for外部i不会失败
}
fn(2);
if(true){
var a=13;
}
console.log(a);//在if定义的变量在外部可以访问
-
对结果进行缓存
var fn=(function(){
var cache={}//将结果缓存到该对象中
return function(){
var str=JSON.stringify(arguments);
if(cache[str]){//判断缓存中是否存在传递过来的参数,存在直接返回结果,无需计算
return cache[str];
}else{//进行计算并返回结果
var sum=0;
for(var i=0;i<arguments.length;i++){
sum+=arguments[i];
}
return cache[str]=sum;
}
}
})()
上面的示例将计算后的结果缓存到局部变量cache当中,在调用这个函数时,先在缓存中查找,如果找不到,则进行计算,然后将结果放到缓存中并返回,如果找到了,直接返回查找到的值。
总结
至此闭包就介绍完了,后续我会给大家介绍一下预编译。如果大家还有其他不同的理解或者是建议,还请在下发留言。如果有理解的不正确的地方还请多多指教。