JavaScript 的核心机制有个特点:它们是互相咬合的,单独背任何一个都记不牢。闭包要靠作用域才能解释清楚,async/await 要靠 Promise 才能解释清楚,Promise 的执行时机又要靠 Event Loop 才能解释清楚。
所以这个专题不按「知识点清单」组织,而是按依赖顺序排。前面的没搞明白,后面的就只能死记。
学习路径
第一步:变量与作用域。 从 var/let/const 的差异入手,理解声明提升、暂时性死区、作用域链的查找过程。这是所有后续内容的地基。
第二步:闭包。 闭包不是一个需要单独记忆的特性,它是词法作用域的自然结果。理解了「函数记住的是定义时的作用域,不是调用时的」,闭包就是显然的。
第三步:this。 这是唯一一个不遵循词法作用域的东西——this 由调用方式决定,不是由定义位置决定。正因为它和前两步的规则相反,才特别容易错。配合 call/apply/bind 一起看。
第四步:Event Loop。 单线程语言怎么处理异步。这一步讲清调用栈、Web APIs、宏任务队列、微任务队列四者的关系。
第五步:Promise 与 async/await。 有了 Event Loop 的框架,Promise 的执行时机就不再神秘。建议配合手写 Promise 一起看——对着 Promises/A+ 规范实现一遍,比看十篇讲解都管用。
第六步:迭代器、生成器、Proxy、Reflect。 这几个是元编程层面的能力,Vue 3 的响应式就建立在 Proxy 上。
几个高频概念的关系
| 概念 | 由什么决定 | 常见误解 |
|---|---|---|
| 作用域 | 代码书写位置(词法) | 以为和调用位置有关 |
| 闭包 | 作用域的自然结果 | 当成需要特殊语法的特性 |
| this | 函数调用方式 | 套用作用域规则去推 |
| 宏任务 / 微任务 | 任务来源 | 以为 setTimeout(fn, 0) 是立即执行 |
| Promise 状态 | 一旦流转不可逆 | 以为可以从 rejected 改回 pending |
常见误区
背了闭包定义,遇到题还是不会。 因为定义是结论不是推导。正确的路径是先把作用域链讲明白,闭包就成了「函数持有了外层作用域的引用,所以外层执行完了那些变量也不销毁」这句话,不需要额外记。
以为 setTimeout(fn, 0) 会立刻执行。 它只是把回调交给浏览器计时,时间到了进宏任务队列。前面还排着整个同步代码和全部微任务。
分不清微任务是「清空」还是「取一个」。 是清空。每个宏任务之后引擎会反复取微任务直到队列为空——包括执行过程中新产生的微任务。这也是为什么无限产生微任务会卡死页面。
用箭头函数解决所有 this 问题。 箭头函数没有自己的 this,它捕获定义时外层的 this。这在回调里很方便,但在需要动态 this 的场景(对象方法、原型方法、需要 call 改变指向的函数)里是错的。
觉得防抖和节流是面试题,工作里用不到。 恰恰相反:搜索框输入、滚动加载、窗口 resize、按钮防重复提交,这些日常需求都要用,而且用错一个会直接变成线上 bug。
本专题全部文章
- 闭包这东西,我来说说我是怎么真正理解它的JavaScript 闭包真正讲明白:不从定义出发,而是先讲清词法作用域,再推导闭包是怎么自然产生的。附常见代码题的分析过程,以及闭包造成内存泄漏的实际情形。
- Event Loop 到底是什么,我用大白话解释一遍Event Loop 事件循环讲透:从一段输出顺序题入手,讲清调用栈、任务队列、宏任务与微任务的关系,以及为什么 Promise 回调总是先于 setTimeout 执行。
- 防抖和节流:不只是面试题,说说工作里怎么用的防抖与节流的区别和选用:防抖是停止触发后才执行,节流是固定间隔执行一次。讲清两者的实现代码,以及搜索输入、滚动加载、按钮防重复等场景该选哪个。
- this、call、apply、bindJavaScript this 指向与 call/apply/bind:this 指向为什么是可变的、五种调用方式下分别指向谁,以及 call、apply、bind 三者在传参形式与返回值上的区别。
- 认识关键字 var/let/constvar、let、const 的区别:作用域范围、变量提升与暂时性死区、能否重复声明、能否重新赋值,以及 const 声明对象时内部属性为何仍可修改。
- 作用域与变量提升JavaScript 作用域与变量提升:全局、函数、块级三种作用域的划分规则,var 的声明提升与 let/const 的暂时性死区,以及作用域链的查找过程。
- 变量定义JavaScript 变量与常量基础:变量的本质是内存中一块命名的存储空间,讲清声明、赋值、命名规则,以及变量与常量在使用上的根本差异。
- 手写 Promise:对照 Promises/A+ 规范从零实现手写 Promise 实现:对照 Promises/A+ 规范从零实现,讲清状态机、then 的链式返回、异步回调队列、值穿透与 thenable 兼容,理解规范每条约束背后的原因。
- Promise 完整指南:状态流转、链式调用与四个静态方法Promise 详解:三种状态与不可逆的流转、then/catch/finally 的链式行为、all/race/allSettled/any 四个静态方法的差异。
- JavaScript Reflect 反射对象:与 Proxy 配对的 13 个静态方法Reflect 反射对象详解:它与 Proxy 捕获器一一对应的设计意图、把 Object 上的命令式操作改成函数式调用的好处,以及在 Proxy 中配合使用的标准写法。
- JavaScript Proxy 代理详解:拦截器用法与元编程实践Proxy 代理详解:在目标对象前架设拦截层的元编程机制,get/set/has/deleteProperty 等 13 种捕获器的触发时机与用法,以及做数据响应式的典型场景。
- Generator 生成器函数:yield 暂停机制与双向通信Generator 生成器函数详解:function* 与 yield 的执行暂停机制、返回的遍历器对象怎么用、next 传参的双向通信,以及 Generator 作为状态机与异步方案的两种理解角度。
- Iterator 迭代器与 for...of:可迭代协议与自定义遍历Iterator 迭代器与 for...of 详解:可迭代协议与迭代器协议各自要求什么、原生哪些结构可迭代,以及怎么给自定义对象实现 Symbol.iterator 让它支持 for...of。
- async/await 用法详解:返回值、错误处理与执行顺序async/await 用法详解:async 函数的返回值语义、await 只能出现在 async 内部的语法约束、错误捕获的正确写法,以及它与 Promise 链和 Generator 的关系。




