
ES6+ 语法指的是 ECMAScript 2015 (ES6) 以及之后所有版本(ES2016, ES2017, ES2018, ES2019, ES2020, ES2021, ES2022, ES2023 等)中引入的新 JavaScript 语言特性和语法糖。
核心点: TypeScript 的核心优势之一就是它允许你使用这些现代、更强大、更简洁的语法(ES6+)来编写代码,然后通过编译器 (tsc
) 将这些代码转换成能在旧版浏览器(如 IE11)或老版本 Node.js 环境中运行的、兼容性更好的 ES5 (或 ES3) 代码。
以下是 ES6+ 主要版本引入的一些关键特性,TypeScript 都能很好地处理它们:
ECMAScript 2015 (ES6) - 里程碑式更新
- 类 (
class
): 基于类的面向对象编程语法糖(最终被编译成 ES5 的函数和原型链)。 - 模块 (
import
/export
): 官方的模块系统,取代了之前的 CommonJS 和 AMD 等方案(编译成require
/module.exports
或命名空间等)。 - 箭头函数 (
() => {}
): 简洁的函数写法,自动绑定词法作用域的this
(编译成普通函数,必要时使用var _this = this
等技巧处理this
)。 - 模板字符串 (
string ${expression}
): 支持嵌入表达式和多行字符串(编译成字符串拼接+
)。 - 解构赋值 (
const {a, b} = obj;
,const [x, y] = arr;
): 从数组或对象中提取数据赋值给变量(编译成对属性/元素的逐个访问)。 - 默认参数值 (
function(param = defaultValue) {}
): 为函数参数设置默认值(编译成param === void 0 ? defaultValue : param
检查)。 - 剩余参数 (
function(...args) {}
): 将不定数量的参数表示为一个数组(编译成对arguments
的处理或数组切片)。 - 展开运算符 (
...arr
,...obj
): 在函数调用、数组字面量、对象字面量中展开可迭代对象或对象属性(编译成concat
,Object.assign
或循环)。 let
和const
: 块级作用域变量声明(编译成var
,必要时使用立即执行函数表达式 (IIFE) 模拟块级作用域)。- Promise: 处理异步操作的标准方式(需要引入 polyfill 库如
es6-promise
才能在旧环境运行,TS 只处理语法)。 - 迭代器 (
Iterator
) 和 生成器 (function*
,yield
): 为可迭代对象(如Array
,Map
,Set
)提供统一的遍历接口,生成器简化迭代器创建(编译成复杂的状态机代码)。 for...of
循环: 遍历可迭代对象(编译成基于数组索引的for
循环或while
循环操作迭代器)。- Map, Set, WeakMap, WeakSet: 新的数据结构(需要运行时 polyfill)。
Symbol
: 唯一的、不可变的值,常用作对象属性的键(需要运行时 polyfill)。- Proxy, Reflect: 元编程特性(通常需要目标环境原生支持或复杂 polyfill,编译层面难以完全模拟)。
- 二进制和八进制字面量 (
0b1010
,0o755
): (编译成对应的十进制数字)。 - 新的字符串方法 (
includes()
,startsWith()
,endsWith()
,repeat()
等): (如果目标环境不支持,编译时可能注入辅助函数或依赖 polyfill)。 - 新的数组方法 (
Array.from()
,Array.of()
,find()
,findIndex()
,includes()
等): (同上,需要 polyfill 或辅助函数)。 - 对象属性简写 (
{ a, b }
)、方法简写 ({ method() {} }
)、计算属性名 ({ [key]: value }
): (编译成 ES5 的对象字面量语法)。
ECMAScript 2016 (ES7)
- 数组
includes()
方法: (已在 ES6 提及,但正式标准化在 ES2016)。 - 指数运算符 (
**
): (编译成Math.pow()
调用)。
ECMAScript 2017 (ES8)
async
/await
: 基于 Promise 的异步编程语法糖,使异步代码看起来像同步代码(编译成生成器函数 +yield
或状态机,通常需要regenerator-runtime
polyfill)。Object.values()
/Object.entries()
: (需要 polyfill 或辅助函数)。- 字符串填充 (
padStart()
/padEnd()
): (需要 polyfill 或辅助函数)。 - 函数参数列表和调用中的尾逗号: (语法糖,编译时保留或去除)。
SharedArrayBuffer
和Atomics
: 用于共享内存和多线程(高级特性,依赖运行时支持)。
ECMAScript 2018 (ES9)
- 异步迭代 (
for await...of
): 遍历异步可迭代对象(编译成复杂的基于生成器和 Promise 的代码)。 - Rest/Spread 属性 (
...
in object literals): 对象解构中的剩余属性和展开属性(编译成Object.assign()
或循环)。 - Promise
finally()
: 无论 Promise 状态如何都会执行的回调(需要 polyfill)。 - 正则表达式改进: 命名捕获组 (
(?<name>...)
)、后行断言 ((?<=...)
,(?<!...)
)、Unicode 属性转义 (\p{...}
,\P{...}
)、s
(dotAll) 标志(需要目标环境或运行时库支持正则引擎)。
ECMAScript 2019 (ES10)
- 数组
flat()
/flatMap()
: (需要 polyfill 或辅助函数)。 Object.fromEntries()
: (需要 polyfill 或辅助函数)。- 字符串
trimStart()
/trimEnd()
: (需要 polyfill 或辅助函数)。 - 可选的
catch
绑定 (catch {}
): (语法糖,编译成catch(e) { /* ignore e */ }
)。 Function.prototype.toString()
改进: 返回包含注释和空格的原始源代码(依赖运行时实现)。Symbol.prototype.description
: (需要 polyfill)。
ECMAScript 2020 (ES11)
BigInt
: 表示任意精度的整数(后缀n
,123n
)(需要目标环境原生支持或 BigInt 库)。- 动态导入 (
import()
): 按需异步加载模块(编译成 Promise +require
或类似机制)。 - 空值合并运算符 (
??
): 提供默认值,仅当左侧为null
或undefined
时返回右侧(编译成三元运算符a !== null && a !== void 0 ? a : b
)。 - 可选链操作符 (
?.
): 安全地访问嵌套对象属性,避免因中间属性为null
/undefined
而报错(编译成一系列&&
检查或三元表达式)。 Promise.allSettled()
: (需要 polyfill)。globalThis
: 统一的全局对象引用(需要 polyfill 或条件判断window
/global
/self
)。
ECMAScript 2021 (ES12)
- 字符串
replaceAll()
: (需要 polyfill 或辅助函数(使用split
+join
或带g
标志的replace
))。 Promise.any()
: (需要 polyfill)。- 逻辑赋值运算符 (
&&=
,||=
,??=
): (编译成对应的逻辑判断 + 赋值语句)。 - 数值分隔符 (
1_000_000
): (语法糖,编译时去除_
)。 WeakRef
和FinalizationRegistry
: 弱引用和清理回调(高级特性,依赖运行时支持)。
ECMAScript 2022 (ES13)
- 类字段声明 (Public/Private Instance Fields): 直接在类中声明实例属性 (
class C { field = 1; #privateField = 2; }
)(私有字段#
编译成WeakMap
或 Symbol 模拟)。 - 类静态块 (
static { ... }
): 类内部的静态初始化块(编译成在类定义后执行的代码)。 - 使用
in
检查私有字段 (#field in instance
): (编译成访问模拟私有字段的存储)。 - 顶层的
await
: 在模块顶层使用await
(编译成异步模块加载模式)。 at()
方法 (Array, String, TypedArray): (arr.at(-1)
)(需要 polyfill 或辅助函数)。Object.hasOwn()
: (Object.hasOwn(obj, prop)
) 更安全地替代obj.hasOwnProperty(prop)
(需要 polyfill)。
ECMAScript 2023 (ES14)
- 通过拷贝改变数组的方法 (
toSorted()
,toReversed()
,toSpliced()
,with()
): 返回新数组,不修改原数组(需要 polyfill)。 Symbol
作为 WeakMap 键: (依赖运行时支持)。Array
查找从最后开始 (findLast()
,findLastIndex()
): (需要 polyfill)。
TypeScript 如何处理这些语法
- 语法降级 (Downleveling): 对于 核心语法结构 (类、模块、箭头函数、解构、
async
/await
、可选链、空值合并等),TypeScript 编译器 (tsc
) 会将其重写(转译)为功能等效的 ES5(或更低)代码。这个过程是 TypeScript 的核心价值所在。 - 辅助函数注入: 对于某些特性(如
__extends
用于类继承、__awaiter
/__generator
用于async
/await
和生成器、__spreadArray
用于展开运算符等),TypeScript 会在编译输出中注入必要的运行时辅助函数。 - Polyfill 依赖: 对于 新的内置对象 (
Promise
,Map
,Set
,Symbol
) 和 新的内置方法 (Array.prototype.includes
,String.prototype.padStart
,Object.values
等) ,TypeScript 编译器 只处理语法,不提供实现 。你需要使用如core-js
或es6-shim
这样的 polyfill 库,在旧环境中提供这些 API 的实现。TypeScript 的lib
编译选项控制着它知道哪些环境 API 的类型定义,但不影响运行时实现。 - 目标环境配置 (
target
): 在tsconfig.json
文件中,通过"target": "es5"
(或"es3"
)设置,明确告诉 TypeScript 编译器需要将代码降级到什么版本的 ECMAScript 标准。这个设置直接影响编译器的降级策略和生成的辅助函数。
总结
"ES6+ 语法" 是一个泛指,涵盖了从 ES2015 (ES6) 开始至今 ECMAScript 规范引入的所有现代化 JavaScript 特性。TypeScript 的核心能力在于将这些新语法**编译(降级/转译)**成兼容旧环境(如 ES5)的代码,并通过辅助函数和依赖 polyfill(由开发者引入)来模拟新的内置对象和方法,从而让你能安全、高效地使用现代语法开发,同时保证代码在旧浏览器或运行时的兼容性。tsconfig.json
中的 target
选项是控制编译输出兼容性的关键。