闭包的概念:
在计算机科学中,闭包(也称词法闭包或函数闭包)是指一个函数或函数的引用,与一个引用环境绑定在一起。这个引用环境是一个存储该函数每一个非局部变量(也叫自由变量的表)。已晕^^
闭包,不同于一般的函数,它允许一个函数在立即词法作用域外调用时,仍然访问非本地变量 ——from维基百科
闭包其实就是能够读取其他函数内部变量的函数。
由于在javascript语言中,只由函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”
所以,在本质上,闭包就是将函数内部和函数外部链接起来的一座桥梁
——form阮一峰
理解闭包需要先了解一下“变量作用域”和“如何读取局部变量”的概念:
一、变量的作用域:
变量的作用域无非就是两种:全局变量和局部变量
javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。
var scope = "local scope";
function outer(){
console.log(scope);
}
outer(); //local scope
另一方面,在函数外部自然无法读取函数内的局部变量:
function outer(){
var scope = "local scope";
}
outer();
console.log(scope);
大家想下,上述的结果会是肿么样呢?
答案当然是大家所想的error了: scope is not defined
还有一个需要注意的地方,函数内部声明变量的时候,一定要使用var关键字,如果不用的话,那么你实际上是声明了一个全局变量
function outer(){
scope = "local scope";
}
outer();
console.log(scope);
???这个的答案是啥呢? local scope 所以要记得使用var关键字额
二、如何从外部读取局部变量?
读取局部变量?刚刚不是说无法读取到函数内的局部变量me?晕了^^
其实是酱紫的,通常情况下是无法读取到函数内部的局部变量的,不过通过变通方法就可以实现鸟!
那就是在函数的内部,再定义一个函数。
function outer(){
var scope = "local scope";
function inner(){
console.log(scope);//local scope
}
}
在上面的代码中,函数inner被包含在函数outer内部,这时outer内部的所有变量,对inner都是可见的。但是反过来就不行了,inner内部的局部变量,对outer是不可见的。这就是javascript语言特有的“链式作用域”结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。
既能inner可以读取outer中的局部变量,那么只要把inner作为返回值,我们就可以在outer外部读取它的内部变量了吗!
function outer(){
var scope = "local scope";
function inner(){
console.log(scope)
}
return inner;
}
var func = outer();
func();
这次的结果会是 scope is not defined 吗?
大家去验证下吧。
其实答案是这样子的 local scope
上述代码中inner函数,就是闭包
闭包的用途
闭包可以用在很多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的局部变量,另一个就是让这些变量始终保持在内存中。
function outer(){
var n = 999;
nAdd = function(){n+=1};
function inner(){
alert(n);
}
return inner;
}
var result = outer();
result(); //999
nAdd();
result(); //1000
在这段代码中,result实际上就是闭包inner函数,它一共运行了两次,第一次的值是999,第二次的值是1000,这证明了,函数outer中的局部变量n一直保存在内存中,并没有在inner调用后自动清除。
使用闭包的注意点
闭包灵活和方便,
闭包也存在“空间浪费”,“内存泄漏”,“性能消耗”的问题,所以不能滥用闭包。
热门评论
写的不错~我老师说心里要有内存~闭包 好像就是内部的函数操作外层函数局部变量使外层函数的活动对象不能被释放~我的天 我在说什么
阮一峰
写的东西还是挺通俗易懂的,很早就看过了,不错
因为nAdd是全局变量,定义时前面没加var