JS深入系列之闭包
五月 31, 2021
本文共计:
802 字
预计阅读时长:
3分钟

今天是儿童节,然鹅,学习还是要的,但是还是要祝各位大朋友,儿童节快乐~~~
紧接着上一篇的内容,我们来回顾一遍JS闭包。
什么是闭包?
列举下我所看到的相对比较官方的解释:
- 闭包是指那些能够访问自由变量的函数。— MDN
- 从技术角度来讲,所有函数都是闭包。 — 《JavaScript权威指南》
那意味着:
1 | const temp = 123; |
上述代码也相当于是闭包。
但是ECMAScript中的规范定义,闭包即便是上下文销毁,也依旧存在,且保持着对于自由变量的引用。
自由变量是指在函数中使用的,但既不是函数参数也不是函数的局部变量的变量。
补充:这里的函数指的是闭包函数。
例如:
1 | function localScope() { |
1 | # print console |
现在,你可以清楚的看到闭包的魅力。
下面过两道面试必刷题:
题目来源于:https://github.com/mqyqingfeng/Blog/issues/9
题目一
1 | var data = []; |
解析过程请参见:https://github.com/mqyqingfeng/Blog/issues/9
题目二
请写一个计时器,每隔一秒打印一次。
这道题,虽然实现思路很多,其实就像考察闭包!下面我来列举下常规解法:
解法一
1 | for(let i = 0; i<60;i++) { |
why?为什么这样写可以呢?我想市面上百分之50的回答应该都是:
因为
let可以创建块作用域,完了结束。
其实我这里再出一段代码:
1 | let i = 0 |
结果肯定不是预期,但是我也用了 let,请思考一分钟。
for循环头部的let声明有一个特殊的行为,在每次循环的时候不止被声明一次,每次迭代都会声明,且初始值用上次的,也就是会出现下面的伪代码:
1 | // 第一次 |
现在能看懂吧,第二个写法虽然用了let,但是它不在for循环头部。
解法二
闭包现身
1 | for (var i = 0; i < 60; i++) { |
1 | for (var i = 0; i < 60; i++) { |
上述两种写法,应该是比较常见的闭包写法,其实就是前文提到的自由变量与闭包作用域。
当函数可以记住并且访问所在词法作用域,即使函数是在当前词法作用域外执行的,这时候就产生了闭包。
—– 《你不知道的JavaScript》上卷 p57
查看评论