一、javascript闭包是什么?
闭包的官方定义是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
其实通俗来讲就是:闭包就是将函数内部和函数外部连接起来的一座桥梁,通过这个桥梁我们可以读取到一个函数内部的变量,在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”,我们也把这个函数叫闭包。
二、变量的作用域
变量的作用域有两种:全局变量和局部变量。在Javascript语言中,函数内部可以直接读取全局变量。
列如:
var x=1;
function test(){
alert(x);
}
test(); // 1
但是JS在函数外部是无法读取到函数的局部变量
function test(){
var x=1;
}
test();
alert(x); // error
三、如何从外部读取一个函数的局部变量
正常情况下我们是无法直接从外部读取到局部变量的,这时候我们需要通过一种方法来实现我们的想法,闭包应运而生,即在这个函数内部嵌套一个子函数,再将这个子函数返回出来。
function test(){
x=1;
function test2(){
alert(x);
}
return test2;
}
var tmp=test();
tmp(); // 1
四、闭包的用途
闭包的用途:可以读取函数内部的变量,让这些变量的值始终保持在内存中,防止全局变量污染,私有成员。
function test(){
var x=1;
test2=function(){
x+=1
}
function test3(){
alert(x);
}
return test3;
}
var tmp=test();
tmp(); // 2
test2();
tmp(); // 3
在这段代码中,tmp实际上就是闭包test3函数。它一共运行了两次,第一次的值是1,第二次的值是2。这证明了,函数test中的局部变量x一直保存在内存中,并没有在test调用后被自动清除,而原因就在于test是test3的父函数,而test3被赋给了一个全局变量,这导致test3始终在内存中,而test3的存在依赖于test,因此test也始终在内存中,不会在调用结束后,被垃圾回收机制回收。这段代码中“test2=function(){x+=1}”这一行,首先在test2前面没有使用var关键字,因此 test2是一个全局变量,而不是局部变量,其次,test2的值是一个匿名函数,而这个匿名函数本身也是一个闭包,所以test2相当于是return,可以在函数外部对函数内部的局部变量进行操作。
上面代码也可这样书写(模块化)
var tmp=(function(){
var x=1;
return function(){
x+=1;
alert(x);
}
})();
tmp();//2
tmp();//3
私有化
var tmp=(function(){
var x=1;
function test1(){
x+=1;
alert(x);
}
function test2(){
x+=1;
alert(x);
}
return{
a:test1,
b:test2
}
})();
tmp.a();//2
tmp.b();//3
五 闭包函数的弊端
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,解决方法是,在退出函数之前,将不使用的局部变量全部清除。