1 前言
如果能够阅读我的上一篇从 JS 执行机制理解变量提升等特性,相信能够有更多的思考~
闭包的用处还是很多的,俺就是在学习 React 的时候了解到 hook也用到了 JavaScript 的闭包机制,所以前来总结学习。
对于闭包,了解一直不深刻,就记得是:在函数 A 里面返回一个函数 B,这样然后在别处调用,这样就能通过函数 B,访问到函数 A里面的变量,即使函数 A 已经执行完毕销毁了,函数 B 仍然能够访问那些变量。
var local = '小林别闹';
function foo() {
var local = 1;
function bar() {
local++;
return local;
}
return bar;
}
var f1 = foo();
console.log(f1());//2
console.log(f1());//3
console.log(f1());//4
var f2 = foo();//新定义的函数,和上面那个是隔开的的,所以下面输出的是2,而不是4
console.log(f2());//2
console.log('local', local);//小林别闹 没有闭包作为接口,只能访问到全局变量local
复制代码
执行结果如图:

1.1 目的
这篇文章主要解决两个问题:
- 加深对于闭包的理解
- 理解闭包与垃圾回收机制的关系
正常来说,当 foo 函数执行完毕之后,其作用域是会被销毁的,然后垃圾回收器会释放那段内存空间。而闭包却很神奇的将 foo 的作用域存活了下来, fn1 依然持有该作用域的引用,这个引用就是闭包。
2 垃圾清除机制
仔细观察文章开头的代码:你难道没有疑惑嘛?俺有。为什么 f1 和 f2 取得的变量是独立,互不干扰的呢,为什么 f1 重复执行,返回的是 2,3,4….,而不是2呢?函数执行完毕不是会销毁的嘛?
首先解决第一个问题: f1 和 f2 是 foo 函数分别执行的结果,函数有函数作用域,就相当于local 变量在两个作用域分别声明,当然互相独立,互不干扰了。
第二个问题:其实这和我们的垃圾回收机制的引用计数相关了,如果一个变量的引用不为0,那么他不会被垃圾回收机制回收,引用,就是被调用。这里 f1 引用了 foo 函数,f1 执行的时候自然就用的是同一个 local .
3 看一个经典的闭包
for (var i = 1; i <= 10; i++) {
console.log(i)//打印1-10
setTimeout(function () {
console.log(i);//打印10个11
}, 1000);
}
for (var i = 1; i <= 10; i++) {
(function () {
var j = i;
setTimeout(function () {
console.log(j);
}, 1000);
})();
}//打印1-10
for (let i = 1; i <= 10; i++) {
setTimeout(function () {
console.log(i);
}, 1000);
}//打印1-10
复制代码
3.1 循环1
第一个for 循环里面,上边能按照我们的想法直接打印出1-10,但是在定时器里面,就是打印的10个11
原因:setTimeout是异步的,根据浏览器的事件循环机制,会等到同步操作全部执行完毕之后,才会执行。但是这个时候 i 已经自增到11了,至于为啥是11不是10,可以去了解一下前置++和后置++的区别
3.2 循环2
第二个 for 循环,我们借助了立即执行函数,立即执行函数是同步的,同时函数也拥有作用域,声明一个变量 j 来保存每次迭代的 i,是不是有点 this 和 _this那味。一个小细节, j 需要用 let 或者 var 声明,不然就是全局变量。
3.3 循环3
第三个 for 循环,我们借助 let 和块级作用域。用 var 就相当于在for循环外面定义了一个var i=1,10次输出共用一个 i,用 let 的话,i 只在自己的作用域内有效,一次++循环过去了,就换了个作用域,自己就不起作用了,当然i++ 就会有一个新的i对应这个作用域。i 是 let 声明的,当前的 i 只对本轮循环有效,每一次循环的 i 都是一个新的变量,JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量 i 时,就是在上一轮的基础上进行的
4 闭包的优劣
优势:就是闭包的特性,能够在全局访问到局部的作用域,这样可以设置私有的变量和方法
劣势:闭包会使得函数中的变量都被保存在内存中,内存消耗很大。
因为知识储备原因,不能像很多大佬内样写的透彻,欢迎大佬指点!





















![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)
![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)
