• AaronConlon.dev
  • Talk
  • Weekly
  • 工具
  • 编程
  • 翻译
  • 资讯
  • 通识

ECMAScript 2022新规范

2022年10月05上次更新于 大约 2 年前
编程

一年一度的ECMAScript规范发布,看看今年有什么新内容!

前言

ECMAScript 是标准化的 JavaScript 语言,于 1997 年发布了第一版,现已发展成为世界上使用最广泛的通用编程语言之一。

ECMAScript 2022 Language是 ECMAScript 语言规范的第 13 版,因此我们也可以称之为ES13!

那么,今年新增了哪些内容呢?

类增强

简单来说有以下三点:

  • 属性可以通过以下方式创建

    • 公共的实例字段

    • 静态的公共字段

  • 新增私属性插槽(井号)

    • 私有字段(私有实例字段和私有静态字段)

    • 私有方法和访问器(非静态)

  • 静态的初始化块

直接看代码:


class MyClass {

  instancePublicField = 1; // 公共实例字段

  static staticPublicField = 2; // 静态公共字段



  #instancePrivateField = 3; // 私有实例字段

  static #staticPrivateField = 4; // 静态私有字段



  #nonStaticPrivateMethod() {}

  get #nonStaticPrivateAccessor() {} // 非静态私有访问器

  set #nonStaticPrivateAccessor(value) {}



  static #staticPrivateMethod() {} // 私有静态方法

  static get #staticPrivateAccessor() {} // 静态访问器

  static set #staticPrivateAccessor(value) {}



  static {

    // 静态的初始化块

  }



	constructor(value) {

    this.property = value; // 公共实例字段

  }

}

举一个静态初始化块的例子:


class Translator {

  static translations = {

    yes: 'ja',

    no: 'nein',

    maybe: 'vielleicht',

  };

  static englishWords = [];

  static germanWords = [];

  static { // (A)

    for (const [english, german] of Object.entries(this.translations)) {

      this.englishWords.push(english);

      this.germanWords.push(german);

    }

  }

}

通过使用静态初始化块,我们可以将所有类相关的代码放在类的内部。

上述例子中,可以将初始化两个word数组的过程优化到静态初始化块内部,从而实现我们需要的效果,如果需要还可以访问私有插槽属性。

需要注意的是:

  • 一个类可以有多个静态初始化块

  • 静态初始化块和静态属性可以交错初始化

  • 超类(superclass)的静态初始化块在子类的静态初始化块之前执行

此外,类的私有化属性插槽可以通过in操作符检查,举个例子:


class ClassWithPrivateSlot {

  #privateSlot = true;

  static hasPrivateSlot(obj) {

    return #privateSlot in obj;

  }

}



const obj1 = new ClassWithPrivateSlot();

assert.equal(

  ClassWithPrivateSlot.hasPrivateSlot(obj1), true

);



const obj2 = {};

assert.equal(

  ClassWithPrivateSlot.hasPrivateSlot(obj2), false

);

顶层 await

规范新增顶层await支持,现在我们可以直接在模块内使用顶层await,而不必再额外进入异步函数内再使用await。

看实例:


const res = await fetch("https://jsonplaceholder.typicode.com/todos/1").then(

  (response) => response.json()

);



console.log("res is:", res);

保存上述内容为文件index.mjs,使用node v17.5以上版本或bunjs直接运行:

node index.mjs即可直接获取到输出。

那么,我们可以在什么地方使用这个特性呢?举个例子:


// first.mjs

const response = await fetch('http://example.com/first.txt');

export const first = await response.text();



// main.mjs

import {first} from './first.mjs';

import {second} from './second.mjs';

assert.equal(first, 'First!'); // true

assert.equal(second, 'Second!'); // true

有了顶层await,我们可以像使用同步导出那样直接导出异步的值。

大致等同于以下代码:

first.mjs:


export let first;

export const promise = (async () => { // (A)

  const response = await fetch('http://example.com/first.txt');

  first = await response.text();

})();

main.mjs:


import {promise as firstPromise, first} from './first.mjs';

import {promise as secondPromise, second} from './second.mjs';

export const promise = (async () => { // (B)

  await Promise.all([firstPromise, secondPromise]); // (C)

  assert.equal(first, 'First content!');

  assert.equal(second, 'Second content!');

})();

方便了不少,不是吗?

error.cause

为Error及其子类添加cause属性,更方便地传递错误原因,增强传递错误信息的能力。


function readFiles(filePaths) {

  return filePaths.map(

    (filePath) => {

      try {

        // ···

      } catch (error) {

        throw new Error(

          `While processing ${filePath}`,

          {cause: error}

        );

      }

    });

}

现在,可以访问错误对象的cause属性获取更多详情。

.at()

就像使用python一样使用JavaScript,通过下标访问数组变得容易,具有显式的函数支持,此外跟直接使用[]访问不一样的是,.at()支持传负数参数进行逆序取值。

正则表达式Flag:/d

看例子:


const matchObj = /(a+)(b+)/d.exec('aaaabb');



assert.equal(

  matchObj[1], 'aaaa'

);

assert.deepEqual(

  matchObj.indices[1], [0, 4] // (A)

);



assert.equal(

  matchObj[2], 'bb'

);

assert.deepEqual(

  matchObj.indices[2], [4, 6] // (B)

);

通过d执行的正则表达式匹配,可以得到匹配的元素的起始下标。

Object.hasOwn(obj, propKey)

Object.hasOwn(obj, propKey)提供了一种安全的方式通过属性key检查对象是否含有非继承的目标属性。


const proto = {

  protoProp: 'protoProp',

};

const obj = {

  __proto__: proto,

  objProp: 'objProp',

}



assert.equal('protoProp' in obj, true); // (A)



assert.equal(Object.hasOwn(obj, 'protoProp'), false); // (B)

assert.equal(Object.hasOwn(proto, 'protoProp'), true); // (C)

最后

众所周知:

JavaScript和ECMAScript的区别在于,前者是一个不同平台实现的编程语言,后者是这门语言的标准规范,平台基于此规范实现这门语言。

ECMAScript由TC39标准委员会设计,其成员来自各大科技公司和其他平台等等,每年都会在年中发布最新的规范。

不同的提案经过四个阶段,最终才会进入规范,在进入规范之前不建议使用,因为其始终是不稳定的,关注每年的新增内容即可。

not-by-ainot-by-ai
已读 0%
文章推荐
文章封面
【译文】TanStack Query: 在变更之后自动使查询失效
更新于 2024-08-07
编程翻译
文章封面
JavaScript variable suggestions for rookie
更新于 2024-08-08
编程
GitHubTwitter / XMediumDevJuejin

友情链接

Jimmy
Jimmy
老胡
老胡
Submara
Submara
Bruce Song
Bruce Song
Scarsu
Scarsu
宇阳
宇阳
Steven Lynn's Blog
Steven Lynn's Blog
OJ·Jimmy (Other Jimmy)
OJ·Jimmy (Other Jimmy)
liruifengv - Web 开发者,Astro 项目成员,开源爱好者。
liruifengv - Web 开发者,Astro 项目成员,开源爱好者。