所谓闭包,就是有权访问另一个函数作用域内变量的函数。(也就是说能访问到私有变量)
在JavaScript语言中,变量分为全局变量和局部变量,而其中的全局变量一旦定义,在任何位置都能访问。而局部变量,只有在其作用域范围内,或者其子函数才能被访问到。
那么,如何做到在其作用域范围外,访问到局部变量呢?这时候闭包就充分的发挥作用了,闭包在本质上来说就是把函数内部和外部形成了一个桥梁关系,将其联系在一起。
首先来看一下,如何形成闭包:
function show(){
var n =3;
function f(){
console.log(n)
}
return f;
}
var getShow=show();
getShow();
其答案为 3;
由此可以看出 函数f形成了一个闭包(也可以说闭包的本质就是一个函数)
首先在函数show中形成了一个AO
在函数还没执行时,此时引用如上图
当函数执行后:
在函数执行时将函数f当做返回值返回了,在函数show执行完毕之后就被释放了(因为show的AO被引用,因此不会消失),但是返回值是一个函数,因此可以得到的getshow中存放的f的地址,因而也得到了引用关系,而存放函数f也继承了函数show的所有东西,当然也包括show的AO,因此形成了一个闭合的回路,(即在这个闭合的回路中可以拿到不属于本函数作用域的变量)就此形成了闭包。可以拿到showAO中的3,进行输出。
进阶栗子
var nAdd;
function out(){
var n = 999;
nAdd = function(){
n ++;
console.log(n)
}//nAdd已经形成了一个闭包,因此能访问到out中的n
return function(){
console.log(n);
}//返回一个函数,同样也能访问到n
}
var getN = out();
getN();//999
nAdd();//1000
getN();//1000
在这值得注意的就是,闭包不一定就return一个函数(暴露一个函数名,使其能间接访问)
在进行运算时,首先要看保护变量的最初值(即运算完会改变保护变量别的操作),在进行执行
out{
n:999
nAdd:{
function(){
n ++;
console.log(n)
}
}
()即getN:{
function(){
console.log(n);
}
}
}
即只能在上一级调用变量
闭包的利弊
根据上文的案例可以看出,闭包最大的优点就是可以拿到函数外部的变量,这样防止了变量污染的问题,但是同时,使用闭包会造成内存消耗过大,因此不能滥用和乱用闭包。