Skip to content

ECMAScript 规范简介

ECMAScript 规范(ECMA-262)不是一本“教程”,而是一份语言实现的工程蓝图。它定义了 JavaScript 引擎(如 V8、SpiderMonkey)必须如何工作。

你已经发现了 [[Environment]][[Prototype]][[ThisBinding]][[LexicalEnvironment]] 这些“内部槽”——这说明你已经从“使用者”进入了“观察者”阶段。

现在,我为你系统性地汇总那些真正影响你深度理解 JavaScript 的规范级概念,并解释它们如何串联起你已知的知识。

一、核心:执行模型(Execution Model)

这是你理解“代码如何运行”的基础。

概念位置作用为什么重要
Execution Context(执行上下文)§8.3每次函数调用或脚本执行时创建的“运行时环境”是理解 this、作用域、调用栈的根基
Call Stack(调用栈)隐含在执行上下文管理中后进先出(LIFO)的栈,管理上下文的执行顺序解释递归、爆栈、异步回调的执行顺序
Realm§8.2一组全局对象、内置对象(如 ArrayDate)的集合解释 iframeinstanceof 失效的原因
Job Queue & Event Loop§8.6异步任务(Promise、setTimeout)的队列理解宏任务/微任务、事件循环的核心

你已知的“this”、“作用域”、“闭包”都依赖于 Execution Context 和 Realm。

二、作用域与闭包的底层机制

你已经理解了 [[Environment]],但规范中还有更细的结构。

概念位置作用为什么重要
Lexical Environment(词法环境)§6.2.3包含 环境记录(Environment Record)外部引用(outer)是“作用域链”的真实实现
Environment Record(环境记录)§6.2.4存储变量绑定的实际结构(如对象环境记录、声明式环境记录)解释 varlet 的不同行为
Declarative Environment Record§6.2.4.1用于 letconstfunction(块级)支持块级作用域
Object Environment Record§6.2.4.2用于 with、全局环境变量绑定到对象属性
Global Environment§8.2.3全局作用域的特殊环境,包含 var、函数、let 的分离管理解释为什么全局 let 不挂在 window

闭包的本质:函数创建时,其 [[Environment]] 指向当前 Lexical Environment,形成“捕获”。
即使外层函数执行完毕,只要闭包存在,Environment Record 就不会被 GC。

三、对象与原型系统的内部机制

你已经知道 [[Prototype]] 是内部槽,但还有更多。

概念位置作用为什么重要
[[Prototype]]§6.1.7.2对象的原型链链接__proto__Object.createclass 的基础
[[Prototype]]` 的隐式性[[Get]][[Set]] 等内部方法会自动沿原型链查找属性访问的“自动向上查找”机制理解“继承”的本质
Internal Methods(内部方法)§7.3[[Get]][[Set]][[HasProperty]]代理(Proxy)拦截的就是这些方法
Ordinary vs Exotic Objects§7.2普通对象 vs 特殊对象(如数组、arguments)解释为什么 Arraylength 能自动更新

Proxy 的本质:拦截对象的内部方法([[Get]][[Set]] 等),实现自定义行为。

四、函数与 this 的绑定机制

你已经知道 [[ThisBinding]],但函数的创建和调用更复杂。

概念位置作用为什么重要
[[ThisMode]]§9.4.6函数的 this 模式:lexically(箭头函数)或 global/strict解释箭头函数没有自己的 this
Function Environment Record§9.4.6函数执行上下文的环境记录,包含 [[ThisBinding]][[ThisMode]]this 绑定的实现位置
[[Construct]] vs [[Call]]§7.3.13构造调用(new)和普通调用的区别new 做了什么?
HomeObject§10.2.3super 查找的起点super.method() 是怎么找到父类方法的?

super 的实现:依赖 HomeObject[[Prototype]] 链。

五、类型系统与抽象操作

这是 JavaScript “奇怪行为” 的根源。

概念位置作用为什么重要
ToPrimitive§7.1.1对象转原始值(toString/valueOf解释 [0] == false{} + []
ToString / ToNumber§7.1.12 / §7.1.5类型转换规则+"1"String(obj) 的底层
Abstract Operations第 7 章IsCallableGetVInstanceofOperator所有操作符、方法调用的底层逻辑
SameValue / SameValueZero§7.2.12 / §7.2.13Object.is()=== 的区别为什么 Object.is(-0, +0)false

“==” 的诡异行为:源于 ToPrimitive 和抽象相等比较算法(Abstract Equality Comparison)。

六、模块与作用域的现代机制

概念位置作用为什么重要
Module Environment Record§9.4.8模块作用域的环境记录import 是如何实现“只读绑定”的?
Import/Export Binding§9.4.8模块间的动态绑定import 不是“拷贝”,而是“链接”
Temporal Dead Zone (TDZ)§5.4.2let/const 在声明前访问报错理解“暂时性死区”

ES 模块是“活绑定”import 的值会随 export 变化而变化。

七、你可能还没意识到,但极其重要的概念

概念为什么重要
Agent类似“线程”的概念,一个 Agent 有自己的 Realm、堆栈、堆。多 iframe 或 Web Worker 就是多个 Agent。
Job vs Job QueuePromise 的 then 回调是 微任务(Microtask),属于 PromiseJobs 队列。setTimeout 是宏任务。
Completion Records每个语句执行后返回一个 { [[Type]]: return/break/continue, [[Value]], [[Target]] },解释 try/catch/finally 的控制流。

八、如何阅读规范?

  1. 不要从头读,按需查阅。
  2. 用英文读,中文翻译常有误差。
  3. 结合 V8 博客v8.dev 会解释规范如何实现。
  4. 用《You Don't Know JS Yet》作为导读:它用通俗语言解释规范思想。

总结:你已掌握的“认知钥匙”

你已经拿到了以下“钥匙”:

你已知规范术语作用
“隐式指针”[[Environment]][[Prototype]]作用域链、原型链的链接机制
“执行上下文”ExecutionContext包含 [[LexicalEnvironment]][[ThisBinding]]
“闭包”函数 [[Environment]] 捕获外层环境变量生命周期延长
“this”[[ThisBinding]]执行上下文的状态字段