💡ECMAScript

JavaScript语言的核心特性是在 ECMA-262 标准中定义

2007年,Ajax 的流行开启了动态 Web 应用的新时代,而此时的 JavaScript 正站在一个十字路口。自 1999 年第三版 ECMA-262 发布以来,JavaScript 就没发生过变化。

那时 ECMAScript 4 引入了非常多的规范草案,包括类、模块、经典继承、私有对象方法、可选类型注释、新语法等大大小小的特性。关于 ECMAScript 的更改范围,TC-39 里有两种不同的意见,其中一方认为这个版本试图完成的太多了,他们创建了一个替代提案 ECMAScript 3.1,旨在对现有标准进行增量更改。双方最终没有达成一致,因为他们对语言如何发展有非常不同的观点。

大规模修改 vs 增量修改

2008年,JavaScript 语言之父 Brendan Eich 宣布 TC-39 将专注标准化 ECMAScript 3.1。他们将列出 ECMAScript 4 里主要的语法和特性更改,也会将 ECMAScript 3.1 和 4 的最佳部分整合在一起。ECMAScript 3.1 最终被标准化为 ECMA-262 的第五版,也称 ECMAScript 5。

ECMAScript 4 从未被发布,以免造成混淆。

2015 年,ECMAScript 6 达到了功能完善的状态,被正式命名为 ECMAScript 2015,也简称 ES6。此版本的特性差异巨大,从全新的对象和模式到对现有对象新方法的语法更改,最重要的是它的所有更改都是为了解决开发人员所面临的实际问题。

ECMAScript 6 的开发用了大约四年,TC-39 也意识到周期太长了不好,所以他们改成了每年发布一版以确保新的语言特性能更快地进入开发阶段。更频繁的发布也就意味着 ECMAScript 的每个新版本的新特性都会比 ECMAScript 6 里的少,为了表示这一变化,规范的新版本不再突出版本号而是发布的年份。所以,ECMAScript 6 也叫 ECMAScript 2015,ECMAScript 7 也被正式称为 ECMAScript 2016,TC-39 期望在未来的所有 ECMAScript 版本中使用基于年份的命名系统。

1. ES5 新特性

  1. 全局的不可变值 undefined, NaN, Infinity

  2. 基本类型对应的对象

    1. String 的属性和方法

      1. 支持 [] 访问

      2. String.prototype.split()

      3. String.prototype.substr()

      4. String.prototype.trim()

    2. Number.prototype.toExponential() 优化

  3. Object 静态方法

  4. Function 对象

    1. Function.prototype.bind()

    2. Function.prototype.apply() 支持类数组

    3. thrown function(){} 有正确的 this 值

    4. 函数的 prototype 属性是不可枚举的

    5. 函数 arguments 参数 toStringTag 的值是 'Arguments'

  5. 内置对象

    1. Array 的方法

    2. Date 的属性和方法

      1. Date.now

      2. Date.prototype.toJSON()

      3. Date.prototype.toISOString()

  6. 其它

    1. typeof JSON === 'object'

    2. 内置函数 parseInt() 忽略前导零

    3. 标识符支持零宽字符

    4. 字面量的扩展用法(对象和数组相关)

    5. 未保留的词

    6. 可枚举属性可以被不可枚举属性 shadowed

2. ES6, ES2015

2.1 新增

  1. 语法

    1. 函数:默认参数和剩余参数new.target

    2. 解构(destructuring):声明、赋值、参数

    3. 展开语法(spread syntax):对可迭代对象

    4. Module

    5. 字面量

      1. 模板字面量

      2. 对象字面量的扩展用法

      3. 八进制和二进制

    6. for..of 循环

    7. 正则表达式的 y 和 u 标志

    8. Unicode 的代码点(code point)转义

  2. 绑定

    1. const

    2. let

    3. 块级作用域里的函数声明

  3. 函数

  4. 内置

2.2 优化

内置对象的扩展用法

  1. Object 静态方法

    1. Object.assign()

    2. Object.is()

    3. Object.getOwnPropertySymbols()

    4. Object.setPrototypeOf()

  2. String 的静态方法和实例方法

  3. Array 的静态方法和实例方法

  4. Number

  5. Math

  6. RegExp 的 prototype 属性

  7. 函数的 name 属性

  8. Date.prototype[Symbol.toPrimitive]

3. 2016+ 新特性

ES2016, ES7

  1. 幂运算符 **

  2. Array.prototype.includes()

ES2017

  1. async 和 await 关键字:async function

  2. Object 三个静态方法

    1. values()

    2. entries()

    3. getOwnPropertyDescriptors()

  3. String.prototype.

    1. padStart()

    2. padEnd()

  4. SharedArrayBuffer

  5. Atomics

ES2018

  1. Object 的 ... 操作:rest 和 spread

  2. Promise.prototype.finally()

  3. 异步迭代器

    1. async 生成器

    2. for-await-of 循环

  4. RegExp 相关的四个

    1. s 标志

    2. 命名捕获组

    3. Lookbehind 断言

    4. Unicode 属性转义

ES2019

  1. Object.fromEntries()

  2. Symbol.prototype.description

  3. String 的实例方法

    • trimLeft()

    • trimRight()

    • trimStart()

    • trimEnd()

  4. Array 的实例方法

    • flat()

    • flatMap()

ES2020

  1. 运算符 ?.??

  2. BigInt 类型

  3. String.prototype.matchAll()

  4. globalThis 关键字

  5. import.meta

  6. Dynamic import

  7. Promise.allSettled()

  8. class 私有变量 #

ES2021

  1. String.prototype.replaceAll()

  2. Promise.any()

  3. WeakRef(不阻止对象的垃圾回收)

  4. 逻辑赋值 ||=, &&=, ??=

  5. 数字分隔符 _

    • 比如 1_0002_2223.1415_9260 === 100022223.1415926 结果是 true

    • 比如 0b1110000111110001 === 0b1110_0001_1111_0001 结果是 true

ES2022

  1. Object.hasOwn()

  2. 索引方法 at():支持负数下标

  3. class 相关

    1. instance fields

    2. static fields

    3. private methods

    4. static initialization blocks

  4. Error 的 cause 属性

  5. RegExp 的 d 标识

ES2023

  1. Array.prototype:从数组的末尾开始遍历

    1. findLast()

    2. findLastIndex()

  2. Array.prototype:通过副本更改数组(非破坏性的)

    1. toReversed()

    2. toSorted()

    3. toSpliced()

    4. with()

  3. Symbol 作为 WeakMap 的 key

  4. 词法 #!:参考 Unix 中的,该命令放在脚本第一行,用来指定脚本的执行器

    • 执行脚本文件,之前 node test.js,现在 ./test.js

    • 其中 test.js 文件的第一行写 #!/usr/bin/env node

4. 主要参考

const table = document.getElementById('table-wrapper');
const featureList = [];

let count = 1;
table.querySelectorAll('tr').forEach(tr => {
    let name = tr.className;
    if (name.indexOf('category') != -1) {
        featureList.push(`\n ${count++}`);
        featureList.push(tr.innerText);
    } else if (name.indexOf('supertest') != -1 || (name === '' && tr.getAttribute('significance'))) {
        featureList.push(tr.querySelector('td:first-child a:nth-child(2)').innerText);
    }
});
console.log(featureList.join());

Last updated