TypeScript 编译 ES6+ 语法到兼容的 JavaScript介绍

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 或循环)。
  • letconst 块级作用域变量声明(编译成 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 或辅助函数)。
  • 函数参数列表和调用中的尾逗号: (语法糖,编译时保留或去除)。
  • SharedArrayBufferAtomics 用于共享内存和多线程(高级特性,依赖运行时支持)。

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 或类似机制)。
  • 空值合并运算符 (??): 提供默认值,仅当左侧为 nullundefined 时返回右侧(编译成三元运算符 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): (语法糖,编译时去除 _)。
  • WeakRefFinalizationRegistry 弱引用和清理回调(高级特性,依赖运行时支持)。

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 如何处理这些语法

  1. 语法降级 (Downleveling): 对于 核心语法结构 (类、模块、箭头函数、解构、async/await、可选链、空值合并等),TypeScript 编译器 (tsc) 会将其重写(转译)为功能等效的 ES5(或更低)代码。这个过程是 TypeScript 的核心价值所在。
  2. 辅助函数注入: 对于某些特性(如 __extends 用于类继承、__awaiter/__generator 用于 async/await 和生成器、__spreadArray 用于展开运算符等),TypeScript 会在编译输出中注入必要的运行时辅助函数。
  3. Polyfill 依赖: 对于 新的内置对象 (Promise, Map, Set, Symbol)新的内置方法 (Array.prototype.includes, String.prototype.padStart, Object.values 等) ,TypeScript 编译器 只处理语法,不提供实现 。你需要使用如 core-jses6-shim 这样的 polyfill 库,在旧环境中提供这些 API 的实现。TypeScript 的 lib 编译选项控制着它知道哪些环境 API 的类型定义,但不影响运行时实现。
  4. 目标环境配置 (target):tsconfig.json 文件中,通过 "target": "es5"(或 "es3")设置,明确告诉 TypeScript 编译器需要将代码降级到什么版本的 ECMAScript 标准。这个设置直接影响编译器的降级策略和生成的辅助函数。

总结

"ES6+ 语法" 是一个泛指,涵盖了从 ES2015 (ES6) 开始至今 ECMAScript 规范引入的所有现代化 JavaScript 特性。TypeScript 的核心能力在于将这些新语法**编译(降级/转译)**成兼容旧环境(如 ES5)的代码,并通过辅助函数和依赖 polyfill(由开发者引入)来模拟新的内置对象和方法,从而让你能安全、高效地使用现代语法开发,同时保证代码在旧浏览器或运行时的兼容性。tsconfig.json 中的 target 选项是控制编译输出兼容性的关键。

相关推荐
lexiangqicheng2 小时前
es6+和css3新增的特性有哪些
前端·es6·css3
拉不动的猪3 小时前
都25年啦,还有谁分不清双向绑定原理,响应式原理、v-model实现原理
前端·javascript·vue.js
狂炫一碗大米饭3 小时前
一文打通TypeScript 泛型
前端·javascript·typescript
exploration-earth6 小时前
本地优先的状态管理与工具选型策略
开发语言·前端·javascript
哈贝#6 小时前
vue和uniapp聊天页面右侧滚动条自动到底部
javascript·vue.js·uni-app
Lazy_zheng7 小时前
🚀 前端开发福音:用 json-server 快速搭建本地 Mock 数据服务
前端·javascript·vue.js
用户2519162427117 小时前
ES6之块级绑定
javascript
ZzMemory7 小时前
藏起来的JS(四) - GC(垃圾回收机制)
前端·javascript·面试
林太白7 小时前
前端必会之Nuxt.js
前端·javascript·vue.js
晓晓莺歌7 小时前
vue-router路由问题:可以通过$router.push()跳转,但刷新后又变成空白页面
前端·javascript·vue.js