ES2015-ES2022新特性总结

任何人都可以向标准委员会(又称 TC39 委员会)提案,要求修改语言标准。
一种新的语法从提案到变成正式标准,需要经历五个阶段。每个阶段的变动都需要由 TC39 委员会批准。--《摘自ECMAScript6入门》

  • Stage 0 - Strawman(展示阶段)
  • Stage 1 - Proposal(征求意见阶段)
  • Stage 2 - Draft(草案阶段)
  • Stage 3 - Candidate(候选人阶段)
  • Stage 4 - Finished(定案阶段)

Stage4 完成阶段

2016

  • Array.prototype.include
  • 幂运算符

2017

  • Object.values/Object.entries
  • 字符串填充
    • String.prototype.padStart
    • String.prototype.padEnd
  • Object.getOwnPropertyDescriptors
  • 函数参数列表和调用的末尾逗号
  • Async functions
  • 共享内存和原子锁

2018

  • 提升模板字面量限制 主要针对模板中的 unicode 中的转义字符。
  • 正则表达式 s (dotAll) flag
  • 正则表达式,增加匹配groups。
let re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
let result = re.exec('2015-01-02');
// result.groups.year === '2015';
// result.groups.month === '01';
// result.groups.day === '02';

// result[0] === '2015-01-02';
// result[1] === '2015';
// result[2] === '01';
// result[3] === '02';
  • 解构/赋值。
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x; // 1
y; // 2
z; // { a: 3, b: 4 }
let n = { x, y, ...z };
n; // { x: 1, y: 2, a: 3, b: 4 }
  • 正则表达式,后行(Lookbehind)断言 ES5中,正则只支持先行断言,ES2018中加入了后行断言的支持。 正则表达式的先行断言和后行断言一共有4种形式:

    • (?=pattern) 零宽正向先行断言(zero-width positive lookahead assertion)
    • (?!pattern) 零宽负向先行断言(zero-width negative lookahead assertion)
    • (?<=pattern) 零宽正向后行断言(zero-width positive lookbehind assertion)
    • (?<!pattern) 零宽负向后行断言(zero-width negative lookbehind assertion)
  • Promise.prototype.finally

  • Async异步迭代open in new window

2019

之前的try...catch是一定要加error的

try {
  //...
} catch(error) {
  //...
}

现在

try {
  /...
} catch {
  /...
}
  • JSON超集
  • Symbol.prototype.description
  • Function.prototype.toString 修正
  • Object.fromEntries
  • JSON.stringify 更好的格式化
JSON.stringify('𝌆')
// → '"𝌆"'
JSON.stringify('\uD834\uDF06')
// → '"𝌆"'

// Unpaired surrogate code units will serialize to escape sequences.
JSON.stringify('\uDF06\uD834')
// → '"\\udf06\\ud834"'
JSON.stringify('\uDEAD')
// → '"\\udead"'
  • String.prototype.{trimStart,trimEnd}
  • Array.prototype.{flat,flatMap}

2020

2021

// "Or Or Equals" (or, the Mallet operator :wink:)
a ||= b;
a || (a = b);

// "And And Equals"
a &&= b;
a && (a = b);

// "QQ Equals"
a ??= b;
a ?? (a = b);
function example(opts) {
  // Setters are not needlessly called.
  opts.foo ??= 'bar'

  // No repetition of `opts.baz`.
  opts.baz ??= 'qux';
}

example({ foo: 'foo' })
1_000_000_000           // Ah, so a billion
101_475_938.38          // And this is hundreds of millions

let fee = 123_00;       // $123 (12300 cents, apparently)
let fee = 12_300;       // $12,300 (woah, that fee!)
let amount = 12345_00;  // 12,345 (1234500 cents, apparently)
let amount = 123_4500;  // 123.45 (4-fixed financial)
let amount = 1_234_500; // 1,234,500

0.000_001 // 1 millionth
1e10_000  // 10^10000 -- granted, far less useful / in-range...

2022

  • Class字段
    • 私有实例方法和访问器
    • Public 实例字段 和 Private 实例字段
    • 静态属性 和 私有静态属性
  • ECMAScript 的正则表达式匹配索引 查看更多open in new window
  • Top-level await 查看更多open in new window 使用await时,不再需要与async配套使用。
  • Class 私有属性#private检查
class C {
  #brand;

  #method() {}

  get #getter() {}

  static isC(obj) {
    return #brand in obj && #method in obj && #getter in obj;
  }
}
const array = [{ value: 1 }, { value: 2 }, { value: 3 }, { value: 4 }];

array.find(n => n.value % 2 === 1); // { value: 1 }
array.findIndex(n => n.value % 2 === 1); // 0

// ======== Before the proposal =========== 

// find
[...array].reverse().find(n => n.value % 2 === 1); // { value: 3 }

// findIndex
array.length - 1 - [...array].reverse().findIndex(n => n.value % 2 === 1); // 2
array.length - 1 - [...array].reverse().findIndex(n => n.value === 42); // should be -1, but 4

// ======== In the proposal =========== 
// find
array.findLast(n => n.value % 2 === 1); // { value: 3 }

// findIndex
array.findLastIndex(n => n.value % 2 === 1); // 2
array.findLastIndex(n => n.value === 42); // -1