看了下 ECMAScript 的 active proposals 列表发现了一些有趣的提案这些提案从 stage 1 ~ stage 3 不等有些提案我很期待能实现

1. SIMD.JS - Stage 3

这是个很老的提案但似乎目前只有 Firefox Nightly 实现了SIMD 是指单指令流多数据流同时对一个数据向量中的每一项分别执行操作从而实现在空间上的并行性

上图来自 Wikipedia图中的 4 个处理单元PU分别对每一维数据进行处理SIMD 的应用很明显可以想到 GPU 计算

2. Object Rest / Spread Properties - Stage 3

这个不必多说React 程序员已经用得很溜了

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 }

3. Asynchronous Iterators - Stage 3

这个提案主要提出了异步生成器用于遍历异步生成器的 for-await-of 语句和异步生成器函数

异步生成器与现有的生成器的不同之处在于目前生成器的 next() 返回一个 { value, done } 结构异步生成器则返回一个 Promise<{ value, done }>——因为异步生成器没法在调用 next() 的时候同步返回done要等到异步操作执行完毕之后才知道完成状态

for-await-of 语句则是用于遍历异步生成器的比如

for await (const line of readLines(filePath)) {
  console.log(line);
}

异步生成器函数则是一种异步生成器的构造函数

async function* readLines(path) {
  let file = await fileOpen(path);

  try {
    while (!file.EOF) {
      yield await file.readLine();
    }
  } finally {
    await file.close();
  }
}

看起来跟生成器函数差不多只不过它返回的不再是一个普通的生成器而是一个异步生成器

4. Public Class Fields - Stage 2

现在可以为类定义方法但是没法定义字段这个提议扩充了定义 public field 的语义

class Foo {
  bar = 42;
  static baz = f() + g();
}

new Foo().bar; // => 42
Foo.baz; // f() + g()

5. Promise.prototype.finally - Stage 2

总觉得这是一个本来就应该有的东西许多 Promise方言也有类似的实现

promise.finally(f)promise.then(f, f) 的区别在于

6. Decorators - Stage 2

这个想必也不用说了使用 TypeScript 或者 Babel 的早已经用上了一颗很甜的糖

@frozen class Foo {
  @configurable(false) @enumerable(true) method() {}
}

7. Arbitrary precision integers - Stage 2

提升整型的精度比如说找第 n 个素数

// Takes an Integer as an argument and returns an Integer
function nthPrime(nth) {
  function isPrime(p) {
    for (let i = 2n; i < p; i++) {
      if (p % i === 0n) return false;
    }
    return true;
  }
  for (let i = 2n; ; i++) {
    if (isPrime(i)) {
      if (--nth === 0n) return i;
    }
  }
}

虽然我觉得字面量的表示很难看但是 javascript 里确实迫切需要处理 int64 / uint64 和高精度整型的方法

8. Observable - Stage 1

我是先知道的 ReactiveX后知道有这个提案的ReactiveX 是一个异步编程的 API有各种语言的实现其中 JavaScript 的实现就叫做 RxJS

9. Null Propagation - Stage 1

类似的运算符其实在 CoffeeScript 里就有虽然可能会被滥用但是有了这个运算符之后有些代码真的可以变得优雅

比如说

let firstName = user?.info?.()?.firstName;

原本可能要写成

let firstName;

if (user !== void 0 && user !== null) {
  let info = user.info();
  firstName = (info !== void 0 && info !== null) ? info.firstName : void 0;
}

唯一的问题就是会增加词法分析的成本词法分析器看到 ?. 的时候不知道这是存在运算符也就是这个提案里提出的运算符还是 ?: 三目运算符可能会有人写 foo?.5:1 这样的表达式只有发现 ?. 后面跟的不是十进制数才能把 ?. 作为一个 token

10. do Expressions - Stage 1

函数式的一个提案不过我喜欢

let x = do {
  if (foo()) { f() }
  else if (bar()) { g() }
  else { h() }
};

会返回 do 块里的计算结果上面的代码执行后 x 根据条件可能是 f() 或者 g() 或者 h() 的结果

不过跟上面一个提案一样这个提案同样会增加语法分析的复杂度而且会复杂得多因为要区分 dodo-while只有读到块结束才能知道除非很明显是一个表达式而不是语句