概念
闭包是指有权访问另一个函数作用域中的变量的函数。当函数可以记住并访问所在的词法作用域,即使函数是在当前词法作用域 之外执行,这时 就产生了闭包。
创建闭包的过程
- 在A函数内部声明B函数;.
- A函数的返回值有B函数,这样就会创建涵盖整个包装函数内部作用域的闭包。即是但我们在其他地方调用A函数后,A函数返回B函数,我们通过它可以继续访问到A函数的作用域,而不会因垃圾回收机制使得A函数里的变量被回收。
function fnc(){
var n=123
function f(){
console.log(n);
}
return f;
}
var result=fnc();
result();
上面的例子中函数fuc返回 f 函数,将它赋值给result时,当我们载外部调用result函数,它实际是调用到声明在fnc函数里的f函数,此时它也就可以找到变量n。
实例
计数器
function nums(){
var start=0;
function add(){
return ++start
}
return add;
}
var numsInc=nums();
console.log(numsInc())//1
console.log(numsInc())//2
上面通过闭包来制作计数器,读取nums函数内部start变量,由于闭包的作用,该变量不会因为每次执行函数的结束而被回收。
如果没有使用闭包,每次都会输出1
function nums(){
var start=0;
++start;
return start
}
var numsInc=nums();
console.log(numsInc())//1
console.log(numsInc())//1
循环与闭包
错误示范
function fnc(){
var arr=[];
for(var i=0;i<5;i++){
arr[i]=function(){ //循环为数组赋值为函数
return i;
}
}
return arr//返回数组
}
var f=fnc();
console.log(f[0]())//5
console.log(f[1]())//5
上面输出5的原因是但我们去调用f[0]函数时 这是i已经结束循环,它的值已经是最后一次循环的结果5
运用闭包
function fnc(){
var arr=[];
for(var i=0;i<5;i++){
!(function(n){ //使用自执行函数
arr[i]=function(){
return n;
}
})(i)
}
return arr//返回数组
}
var f=fnc();
console.log(f[0]())//0
console.log(f[1]())//1
es6 let 块级作用域
function fnc(){
var arr=[];
for(let i=0;i<5;i++){
arr[i]=function(){ //循环为数组赋值为函数
return i;
}
}
return arr//返回数组
}
var f=fnc();
console.log(f[0]())//0
console.log(f[1]())//1