闭包
什么是闭包?
简单来说,闭包就是指有权访问另一个函数作用域中的变量的函数。
闭包是一种特殊的对象,由两部分构成:函数,以及创建该函数的环境。环境由闭包创建时在作用域中的任何局部变量组成。环境由闭包创建时在作用域中的任何局部变量组成。
产生一个闭包
创建闭包最常见方式就是在一个函数内部创建另一个函数。
例:
function func( ) {
var a = 1,b = 2;
function closure( ) {
return a+b;
}
return closure;
}
闭包的作用域链包含着它自己的作用域,以及包含它的函数的作用域和全局作用域。
闭包的注意事项
- 闭包只能取得包含函数中任何变量的最后一个值,这是因为闭包所保存的是整个变量对象,而不是某个特殊的变量。
function test(){
var arr = [ ];
for(var i = 0;i < 10;i++){
arr[i] = function(){
return i;
};
}
for(var a = 0;a < 10;a++){
console.log(arr[a]());
}
}
test(); // 连续打印 10 个 10
对于上面的情况,如果我们改变代码如下:
function test(){
var arr = [];
for(let i = 0;i < 10;i++){ // 仅这改动
arr[i] = function(){
return i;
};
}
for(var a = 0;a < 10;a++){
console.log(arr[a]());
}
}
test(); // 打印 0 到 9
- 通常函数的作用域及其所用变量都会在函数执行结束后被销毁,但是,在创建了一个闭包后,这个函数的作用域就会一直保存到闭包不存在为止。
function markAdder(x){
return function(y){
return x+y;
}
}
var add5 = makeAdder(5);
var add10 = makeAdder(10);
ocnsole.log(add5(2)); // 7
console.log(add10(2)); // 12
//释放对闭包的引用
add5 = null;
add10 = nul;
add5和add10都是闭包。他们共享相同的函数定义,但是保存了不同的环境。在add5的环境中,x为5,而在add10中,x为10,最后释放了对闭包的引用。
- 闭包只能取得包含函数中任何变量的最后一个值,这是因为闭包所保存的是整个变量对象,而不是某个特殊的变量。
闭包的应用
任何在函数中定义的变量,都可以认为是私有变量,因为不能在函数外部访问这些变量。私有变量包含函数的参数,局部变量和函数内定义的其他函数。
把有权访问私有变量的公有方法称为特权方法。
function Animal( ){
//私有变量
var series = "哺乳动物";
function run( ){
console.log("Run!!!");
}
//特权方法
this.getSeries = function(){
return series;
};
}
- 模块模式:为单例创建私有变量和方法。
- 单例:指的是只有一个实例的对象。JavaScript 一般以对象字面量的方式来创建一个单例对象
闭包的缺陷
- 闭包的缺点就是常驻内存会增大内存使用量,并且使用不当很容易造成内存泄露
- 如果不是因为某些特殊任务而需要闭包,在没有必要的情况下,在其它函数中创建函数是不明智的,因为闭包对脚本性能具有负面影响,包括处理速度和内存消耗。