先写段代码举例
var aa = '1'
function bb() {
console.log(aa)
}
上面代码就是一个闭包。
如果一个函数,使用了它范围外的变量,那么(这个函数+这个变量)就叫做闭包
闭包的两大好处:
- 一个可以读取函数内部的变量
- 另一个就是让这些变量的值始终保持在内存中
闭包一般伴随着函数嵌套,有时候要得到函数内的局部变量,就需要在函数内部再定义一个函数
1.读取函数内部的变量
function f1() {
var n = 100;
function f2() {
console.log(n);
}
return f2;
}
var result = f1();
result(); // 100
上面代码中,f2
被嵌套在f1
内部,f1
的全部变量,f2
都是可以访问的。但是反过来不行。所有我们可以把f2
作为返回值,这样f1
就可以访问了。
2.变量的值始终保持在内存中
function f1(){
var n=999;
nAdd=function(){n+=1}
function f2(){
console.log(n);
}
return f2;
}
var result=f1();
result(); // 999
nAdd();
result(); // 1000
f2
是一个嵌套函数的闭包,执行了两次,第一次值是999,第二次是1000.证明了函数f1
的局部变量n
一直保存在内存中,没有在f1
调用后清除。
因为 f1
是f2
的父函数,f2
被赋给了一个全局变量n
,导致f2
一直在内存中,因为f2
在f1
中,故f1
也在内存中。(内存回收是没有任何地方用到这个变量或者函数,那么就被回收)。
其中nAdd
没有用var
定义,是个全局变量。nAdd
后面的函数是匿名函数也是一个闭包,nAdd
相当于一个setter
,可以在函数外部对函数内部的局部变量进行操作。
两个例子
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
console.log(object.getNameFunc()()); //The Window
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
var that = this;
return function(){
return that.name;
};
}
};
console.log(object.getNameFunc()()); //My Object
参考文档:
1.https://zhuanlan.zhihu.com/p/22465092
2.http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html