跳到主要内容

漫长的 JavaScript 的发展史。

ES 1 创业版

JavaScript 语言的雏形,奠定了语言的基本。

  • 原始值NumberStringbooleannullundefined
  • 变量声明:使用 var 关键字声明变量
  • 定义了大部分的运算符、基本流程控制语句、内置对象、函数与对象机制
  • 确立了函数的一等公民的身份
  • 建立了基于原型的继承机制,且内置了核心的内置对象
  • 提出了初步的正则表达式雏形
  • 提出了初步的错误处理机制 try...catch...finally

ES 2 补丁版

在 ECMAScript 2 中并没有添加新的特性,反而是让 [ES1] 更加的规范和正规(符合国际标准化组织规范)

ES 3 重大更新

  • 正则表达式的加强:确立了正则表达式的一等公民身份,明确了字面量语法构造函数 构建表达式及提供了 String 使用方法
  • 异常处理:完善了结构化的错误处理机制(主动抛出错误),让开发者可以更加优雅的捕获和处理运行时的错误,避免程序崩溃,并执行清理工作,显著提高了代码的健壮性和可维护性
  • switch 分支:提供了更优的分支体系
  • do...while 循环:提供了确保循环体至少执行一次的循环结构,优化了原有循环逻辑
  • for...in 循环:提供更便捷的对象可枚举属性的遍历
  • new 运算符的改进:使其创建对象的过程更加明确可控
  • ** ==!= 改进**:规范了其对比时类型强制转化的行为
  • String 对象:新增了
    • charAt():查找给定字符在字符串的索引下标
    • charCodeAt():查找给定字符在字符串的索引下标
    • indexOf():查找给定子串在字符串的位置
    • lastIndexOf()
    • slice()
    • substring()
    • toLoverCase()
    • toUpperCase()
  • Array 对象:新增了
    • concat()
    • join()
    • pop()
    • push()
    • reverse()
    • shift()
    • slice()
    • sort()sort() 还支持传入自定义的比较函数
    • splice()
    • unshift()
  • Date() 对象:增强了日期的处理能力,提供了更精准的毫秒级时间操作方法
  • Function 对象length 属性被标准化,表示函数期望的参数个个数
  • 全局对象isFinite()isNaN() 函数被明确定义和标准化
  • 函数和 this 的增强
    • call()apply() 方法:允许调用函数时执行 this 指向,解决了函数在不同上下文执行时的 this 绑定问题
    • arguments 对象完善:明确 arguments 与函数的“动态绑定”(修改了 arguments[i] 会同步修改对应参数,反之亦然),但后续 ES5 严格模式取消了这一特性

ES 4 失败的激进版

为了让 JavaScript 能够成为一个可以与 Java、C# 竞争、适合大型应用开发的企业级语言,试图从一门动态脚本语言转变成一门更严谨、更适合大规模开发的静态类型语言

所以,ES 4 提案提出了:

  • 强类型系统
  • 模块化
  • 包和命名空间
  • 丰富的集合类型
  • 迭代器和生成器
  • 泛型
  • 多重继承
  • 字符串模版
  • 更大的元编辑能力

但由于太过于极具野心而成为被放弃的版本。

ES 5 里程碑式的版本

  • 严格模式
  • Array 内置对象新增
    • 迭代
      • forEach()
      • map()
      • filter()
      • some()
      • every()
      • reduce()
      • reduceRight()
    • 查找
      • indexOf()
      • lastIndexOf()
  • 还为数组添加了原型方法 Array.isArray(arr) 用于判定一个值是否是数组
  • String 内置对象新增了 trim() 方法
  • Object 对象新增
    • Object.create(proto, [propertiesObjet])
    • Object.defineProperty(obj, prop, descriptor)/Object.defineProperties(obj, props)
    • Object.keys(obj)
    • Object.getOwnPropertyNames(obj)
    • Object.getOwnPropertyDescriptor(obj, prop)
    • Object.seal(obj)
    • Object.freeze(obj)
    • Object.preventExtensions(obj)
    • 新增了 getter/setter 属性,使用 getset 关键字定义对象的访问器属性
  • 添加了原生的 JSON 支持
  • 新添了 bind 解决 this 指向问题
  • 新增了 Date.now() 返回当前时间戳

ES 6 可能是最后一次重大升级的版本

  • 添加了
    • letconst 来创建有块级作用域的声明关键字(或称为“变量声明语句”)
    • 模版字符串
    • Symbols 这一原始类型
    • SetMap 两种复合类型的数据
    • ProxyReflect 两个好基友
    • 箭头函数,简化了部分场景下的函数使用
    • 解构赋值
    • 默认参数剩余参数扩展运算符(扩展运算符并未支持 Object,这一特性在 [es9] 才得以引入)
    • class 类这个语法糖
    • 迭代器生成器的官法迭代认证
    • 提供了字符串的 includes()startsWith()endsWith()repeat() 等方法
    • 在正则表达式中添加了 u 修饰符,含义为 Unicode 模式,用于处理大于 \uFFFF 的 Unicode 字符
    • 引入了 Promise ,解决了地狱循环。包含 Promise.resolve()Promise.reject()Promise.all()Promise.race() 静态方法
    • 官方确立了 模块化 的标准
  • 优化了
    • 升级了 Unicode 到支持 5.1.0 版本
    • 增强了对象字面量,可以简写属性同名变量值、方法声明无需使用 : function () {} 格式

ES 7 微小的改进

  • 为数组新增了 includes() 方法,解决了传统的 indexOf() 的局限性
  • 新增了 ** 指数运算符

ES 8 异步变“同步”

  • 为了简化 Promise 的使用,引入了 Async/Await
  • 为对象引入了
    • Object.value()
    • Object.entries()
    • Object.getOwnPropertyDescriptors()
  • 字符串填充 padStart()padEnd() 简化了文本的格式化输出
  • 函数参数列表和调用中的尾逗号不在影响代码的执行
  • SharedArrayBuffer 共享内存
  • 提供了 Atomics 原子操作

ES 9 异步迭代和正则表达式的增强

  • 新增了
    • 异步迭代异步可迭代对象,提供了 for-await-of 用于遍历异步数据
    • Promise.prototype.finally() 避免了部分代码的重复(好吧,我之前都是封装函数解决的)
  • 扩展了 Rest/Spread 到对象上的使用
  • 正则表达式尽心了加强:
    • 命名捕获组
    • 反向断言
    • Unicode 属性转义
    • ditAll (s 标志)模式,可使 . 匹配包含 \n\r 在内的换行符
  • 模版字符串进行了加强,允许 \u\x 等转义序列而不再报错
  • 可选的 catch 绑定
  • JSON 超集问题,允许 JSON 中出现未转义的终止符(如 \n\r\u2028\u2029

ES 10 中规中矩的增强

  • 添加了
    • Array.prototype.flat()Array.prototype.flatMap() 解决嵌套数组的扁平化处理
    • String.prototype.trimStart()String.prototype.trimEnd() 去除文本空格
    • Object.formEntries() 作为 Object.entries() 的逆向操作,更优雅的构建对象
    • Symbol.prototype.description 用于获取 Symbol 创建时的描述字符串,无描述时返回 undefined
    • 可选的 Catch 绑定
  • 优化了
    • function.prototype.toString() 方法,现返回函数的完整源代码,包含注释、空格、参数默认值等
    • Array.prototype.sort() 的稳定性
    • JSON.stringify()Symbol 的处理
  • 规范了 JSON.stringify() 输出符合标准的 JSON 字符串,避免因为“孤立代理项”导致的无效 JSON

ES 11 面向模块的优化

  • 添加了
    • 可选链式操作符 ?.
    • 空值合并操作符 ??
    • import() 函数允许动态加载模块
    • BigInt 类型以支持大数字
    • String.prototype.matchAll() 解决 match() 无法获取所有捕获组的问题
    • globalThis 统一了全局对象访问
    • Promise.allSettled() 方法用于补充 Promise.all() 有子 Promise 失败就退出
    • 模块化中的 import.meta 来访问模块的元信息
  • 优化了
    • 模块化的命名空间导出
    • for-in 枚举时顺序问题

ES 12 进一步的优化

  • 添加了
    • String.prototype.replaceAll() 来补充 String.prototype.replace()
    • &&=||=??= 等方法,进一步简化某些情况下的赋值
    • 数字分隔符,在不影响数字的值的前提下增强了数字的可读性
    • Promise.any()AggregateError 来返回第一个成功兑现的 Promise 结果
    • WeakRefFinalizationRegistry 来优化对象的“强引用”问题
    • Intl 对象,增强了国际化
  • 优化了 Array.prototype.sort() 方法,提升排序结果的一致性

ES 13 类与对象的强化

  • 添加了
    • 类中属性或方法使用 # 前缀声明为私有属性或方法
    • 静态成员使用 # 前缀声明为私有静态成员
    • 类的静态初始块,用于执行类级别的初始化逻辑
    • 顶层的 await
    • Array.prototype.at() 方法,弥补之前访问元素不便
    • 正则表达式的 d 标志,使 exec()match() 等方法返回的结果包含 indices 属性,记录匹配内容以及捕获组的起始结果索引
    • Error 构造函数的 cause 选项,允许抛出新错误时附加原始错误,形成错误链
    • Object.hasOwn() 代替 Object.prototype.hasOwnProperty.call(obj, prop) 检测对象自身是否有某属性
  • 优化了
    • 类声明字段的声明,可在类中直接声明字段,而不再在 constructor 中使用 this.xxx 声明
    • in 操作符中使用 #fieldName 来检测一个对象是否包含特定的私有字段,而不会抛出错误

ES 14 数组的进一步优化

  • 添加了
    • 数组的 4 个不可变操作
      • Array.prototype.toReversed() 返回一个新的反转数组
      • Array.prototype.toSorted(compareFn) 返回一个新的排序后的数组
      • Array.prototype.toSpliced(start, deleteCount, ...items) 返回更改后一个新的数组
      • Array.prototype.with(index, value) 返回一个指定索引被更改的新数组
    • 数组的新的尾部查找:
      • Array.prototype.findLast(callback, thisArg) 从数组的最后一个元素开始遍历,找到第一个满足条件的元素
      • Array.prototype.findLastIndex(callback, thisArg) 从数组的最后一个元素开始遍历,找到第一个满足条件的元素的索引
    • WeakMap 的键可被设置成使用 Object.freeze()Object.seal() 处理过的对象
    • 正式将 Hashbang 语言纳入标准
    • Object.groupBy 用于数组的统计,简化了传统的 Array.prototype.reduce() 方法进行分组的复杂操作
    • 添加了 @ 装饰器(这货在 AngularNest.js 中用的风生水起)

ES 15 小小的优化

  • 添加了
    • Promise.withResolvers() 直接返回一个包含 promiseresolvereject 的对象,简化 Promise 的创建
    • ArrayBufferSharedArrayBuffer 新功能
    • TypedArray.prototype.with() 不可变修改 TypedArray
    • 正则匹配新的 v 标志,增强了处理 Unicode 的复杂的字符集运算

ES 16 可能还没被支持的大更新

  • 添加了
    • Promise.try() 统一处理同步和异步操作的错误,避免了 Promise.resolver().then() 的微任务延迟问题
    • Set 新增了七个方法:
      • Set.prototype.union() 并集
      • Set.prototype.Intersection() 交集
      • Set.prototype.difference() 差集
      • Set.prototype.symmetricDifference() 对称差集
      • Set.prototype.isSubsetOf() 子集判定
      • Set.prototype.isSupersetOf() 超集判定
      • Set.prototype.isDisjoinFrom() 无交集判定
    • 同步迭代辅助方法,链式结构 map()filter()take()drop()toArray()
    • 通过 with { type: 'json'} 直接导入 JSON 文件,无需手动解析
    • 使用 defer 声明一个预加载模块,延迟到首次调用时才访问引入模块
    • 使用 RegExp.escape() 安全转义正则特殊字符(*?$
    • 在正则表达式中动态启用或禁用标志的功能
    • 在正则表达式中重复命名捕获组
    • 底层支持 Float16Array 类型
    • 通过 using 声明的变量,通过 Symbol.dispose 在作用域结束清理逻辑时,自动释放文件句柄、网络连接等资源,避免内存泄漏
    • 支持对象、数组结构以及条件分支,代替深层嵌套的 if-else(没看懂要干啥)
    • 智能管道符 |> 将连续调用转化为更直观的线式调用
    • 原生的类型注解(与其说是为了干掉 TypeScript,但不如说是变成了 TypeScript)
    • RecordTuple 两种新的深度不可变的数据结构,通过 # 标记数据