闭包简而言之就是通过作用域链逐步访问来获取变量
防止其他函数操控变量来导致代码混乱
function foo(){
var local = 1
function bar(){
local++
return local
}
return bar
}
var func = foo()
func()
首先从var func = foo()开始执行
作用链类似于C语言的堆栈
从全局->foo->bar
在bar中查找local,因为bar中并没有local所以进入foo查找,找到了local并自增,然后返回local
for (var i = 1; i <= 5; i++) {
setTimeout(function timer() {
debugger;
console.log(i); // 输出什么?
}, 1000);
}
这里的代码输出了6 6 6 6 6
全局->for的块级->然后开始设置setTimeout,因为setTimeout是一个异步的代码,1s后执行for已经执行完了,所以会访问for执行后的var i变量
如果想改变有以下方式
for (let i = 1; i <= 5; i++) {
setTimeout(function timer() {
debugger;
console.log(i); // 1 2 3 4 5
}, 1000);
}
因为let有块作用域,所以变成了
全局->for的每个let块作用域->然后开始设置setTimeout
所以获得了每个let块作用域的i
for (var i = 1; i <= 5; i++) {
(function (i) {
setTimeout(function timer() {
debugger;
console.log(i);
}, 1000);
})(i)
}
这里用了立即执行函数,变成了全局->立即执行函数作用域->然后开始设置setTimeout
关于销毁问题(仅为个人理解可能存在问题)
普通函数在执行后会自动回收内存
而闭包不会自动回收变量
这个原因可能是作用域链上存在一个类似引数计数器的东西,防止变量被回收销毁