what:即使函数是在当前作用域外执行,函数也可以记住并访问所在的词法作用域
一些例子:
-
将函数对象本身当作返回值
function foo(){ var a=2; function bar(){ console.log(a); } return bar; }
-
以调用的形式将函数进行传递,且外部函数在内部运行
function foo(){ var a=2; function baz(){ console.log(a); } bar(baz); } function bar(fn){ fn(); }
-
通过将内部函数传递给全局变量来传递出去运行
var fn; function foo(){ var a=2; function baz(){ console.log(a); } fn=baz; } function bar(){ fn(); }
-
只要使用了回调函数,实际上就是在使用闭包
经典循环题/面试题
面试官:来,说说看这个输出的是什么?
for(var i=1;i<=5;i++){
setTimeout(function timer(){
console.log(i);
},i*1000);
}
小A:emmm看上去就是循环输出嘛,从1输出到5?
好的灰掉!
实际上输出的是5个6
这里:尽管循环中五个函数是在各个迭代中分别定义的,但都被封闭在一个共享的全局作用域中,实际上只有一个i,而延迟函数的回调会在循环结束后执行
想要从1输出到5?
解决方法就是:每个迭代都需要一个闭包作用域
方法一:
for(var i=1;i<=5;i++){
(function(){
var j=i;
setTimeout(function timer(){
console.log(j);
},j*1000);
})();
}
改进一下get
方法二:
for(var i=1;i<=5;i++){
let j=i;
setTimeout(function timer(){
console.log(j);
},j*1000);
}
再改进get
方法三:
for(let i=1;i<=5;i++){
setTimeout(function timer(){
console.log(i);
},i*1000);
}