我是靠谱客的博主 寒冷电源,这篇文章主要介绍ECMA 2022 (es13) 新特性,现在分享给大家,希望可以做个参考。

文章目录

    • Class Fields
      • [Private instance methods and accessors](https://github.com/tc39/proposal-private-methods)
      • [Class Public Instance Fields & Private Instance Fields](https://github.com/tc39/proposal-class-fields)
      • [Static class fields and private static methods](https://github.com/tc39/proposal-static-class-features)
    • RegExp Match Indices
    • Top-Level await
    • Ergonomic brand checks for Private Fields
    • .at
    • Object.hasOwn()
    • Class Static Block
    • 参考资料

本文主要整理了截至到 2021年10月12日 为止的且处于 Stage 3->Stage 4 阶段的ECMA提案。

Class Fields

class 相关的提案一共有三个,目前都处于 Stage 3 阶段。

Private instance methods and accessors

示例:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/**** es2015 ****/ class Counter extends HTMLElement { get x() { return this.xValue; } set x(value) { this.xValue = value; window.requestAnimationFrame(this.render.bind(this)); } clicked() { this.x++; } constructor() { super(); this.onclick = this.clicked.bind(this); this.xValue = 0; } connectedCallback() { this.render(); } render() { this.textContent = this.x.toString(); } } window.customElements.define('num-counter', Counter); /**** now(exNext) ****/ class Counter extends HTMLElement { xValue = 0; // 声明共有属性 get x() { return this.xValue; } set x(value) { this.xValue = value; window.requestAnimationFrame(this.render.bind(this)); } clicked() { this.x++; window.requestAnimationFrame(this.render.bind(this)); } constructor() { super(); this.onclick = this.clicked.bind(this); } connectedCallback() { this.render(); } render() { this.textContent = this.x.toString(); } } window.customElements.define('num-counter', Counter);

Class Public Instance Fields & Private Instance Fields

示例:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// es2015 class Counter extends HTMLElement { clicked() { this.x++; window.requestAnimationFrame(this.render.bind(this)); } constructor() { super(); this.onclick = this.clicked.bind(this); this.x = 0; } connectedCallback() { this.render(); } render() { this.textContent = this.x.toString(); } } window.customElements.define('num-counter', Counter); // now class Counter extends HTMLElement { x = 0; clicked() { this.x++; window.requestAnimationFrame(this.render.bind(this)); } constructor() { super(); this.onclick = this.clicked.bind(this); } connectedCallback() { this.render(); } render() { this.textContent = this.x.toString(); } } window.customElements.define('num-counter', Counter); // 结合私有字段 class Counter extends HTMLElement { #x = 0; clicked() { this.#x++; window.requestAnimationFrame(this.render.bind(this)); } constructor() { super(); this.onclick = this.clicked.bind(this); } connectedCallback() { this.render(); } render() { this.textContent = this.#x.toString(); } } window.customElements.define('num-counter', Counter);

Static class fields and private static methods

复制代码
1
2
3
4
5
6
7
8
9
10
11
class Test { static instance = new Test(0);// 静态共有变量 static #value=123; // 静态私有变量 // 静态私有方法 static #print(){ return this.#value; } }

RegExp Match Indices

正则的匹配模式之前只有i g m,现在增加 d,目前处于 Stage 4 阶段。

示例:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const re1 = /a+(?<Z>z)?/d; // indices are relative to start of the input string: const s1 = "xaaaz"; const m1 = re1.exec(s1); m1.indices[0][0] === 1; m1.indices[0][1] === 5; s1.slice(...m1.indices[0]) === "aaaz"; m1.indices[1][0] === 4; m1.indices[1][1] === 5; s1.slice(...m1.indices[1]) === "z"; m1.indices.groups["Z"][0] === 4; m1.indices.groups["Z"][1] === 5; s1.slice(...m1.indices.groups["Z"]) === "z"; // capture groups that are not matched return `undefined`: const m2 = re1.exec("xaaay"); m2.indices[1] === undefined; m2.indices.groups["Z"] === undefined;

使用 d 后给 上面代码中的 m1 增加 indices 属性。

Top-Level await

之前只能 async await, 现在则可以直接使用 await ,目前处于 Stage 4 阶段。

示例:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*** before ***/ // awaiting.mjs import { process } from "./some-module.mjs"; export default (async () => { const dynamic = await import(computedModuleSpecifier); const data = await fetch(url); const output = process(dynamic.default, data); return { output }; })(); // usage.mjs import promise from "./awaiting.mjs"; export default promise.then(({output}) => { function outputPlusValue(value) { return output + value } console.log(outputPlusValue(100)); setTimeout(() => console.log(outputPlusValue(100), 1000); return { outputPlusValue }; }); /*** now ***/ // awaiting.mjs import { process } from "./some-module.mjs"; const dynamic = import(computedModuleSpecifier); const data = fetch(url); export const output = process((await dynamic).default, await data); // usage.mjs import { output } from "./awaiting.mjs"; export function outputPlusValue(value) { return output + value } console.log(outputPlusValue(100)); setTimeout(() => console.log(outputPlusValue(100), 1000);

Ergonomic brand checks for Private Fields

这个提案的作用是检测一个对象中是否存在私有变量,目前处于 Stage 4 阶段。

示例:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
class C { #brand; #method() {} get #getter() {} static isC(obj) { return #brand in obj && #method in obj && #getter in obj; } }

.at

在所有基本可索引类中添加 .at() 方法,目前处于 Stage 3 阶段。

很多时候,类似于 Python 中的数组负值索引可以非常实用。比如在 Python 中我们可以通过 arr[-1] 来访问数组中的最后一个元素,而不用通过目前 JavaScript 中的方式来访问 arr[arr.length-1]。这里的负数是作为从起始元素(即arr[0])开始的反向索引。

但是现在 JavaScript 中的问题是,[] 这个语法不仅仅只是在数组中使用(当然在 Python 中也不是),而在数组中也不仅仅只可以作为索引使用。像arr[1]一样通过索引引用一个值,事实上引用的是这个对象的 "1" 这个属性。所以 arr[-1] 已经完全可以在现在的 JavaScript 引擎中使用,只是它可能不是代表的我们想要表达的意思而已:它引用的是目标对象的 "-1" 这个属性,而不是一个反向索引。

这个提案提供了一个通用的方案,我们可以通过任意可索引的类型(Array,String,和 TypedArray)上的 .at 方法,来访问任意一个反向索引、或者是正向索引的元素。

示例:

复制代码
1
2
3
4
const arr = [1,2]; arr.at(-1); // 2 arr.at(-2); // 1

Object.hasOwn()

采用一种使更易于访问的方法替代 Object.prototype.hasOwnProperty(),目前处于 Stage 4 阶段。

其实现在我们就可以通过 Object.prototype.hasOwnProperty 来使用提案所包含的特性。但是直接通过对象自身的 hasOwnProperty 来使用 obj.hasOwnProperty('foo') 是不安全的,因为这个 obj 可能覆盖了 hasOwnProperty 的定义,MDN 上也对这种使用方式进行了警告。

JavaScript 并没有保护 hasOwnProperty 这个属性名,因此,当某个对象可能自有一个占用该属性名的属性时,就需要使用外部的 hasOwnProperty 获得正确的结果…

示例:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
let hasOwnProperty = Object.prototype.hasOwnProperty if (hasOwnProperty.call(object, "foo")) { console.log("has property foo") } // 此提案将该代码简化为: if (Object.hasOwn(object, "foo")) { console.log("has property foo") }

Class Static Block

类块提供了在类定义评估期间执行额外静态初始化的机制,目前处于 Stage 4 阶段

自从有了 Class Private Fields,对于类的语法是不断地有新的实践与需求。这个提案提议的 Class Static 初始化块会在类被执行、初始化时被执行。

提案中定义的初始化代码块可以获得 class 内的作用域,如同 class 的方法一样,也意味着可以访问类的 #字段

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let getX; export class C { #x constructor(x) { this.#x = { data: x }; } static { // getX has privileged access to #x getX = (obj) => obj.#x; } } export function readXData(obj) { return getX(obj).data; }

参考资料

  • ECMAScript 双月报告:Pipeline Operator 进入 Stage 2(2021/8)
  • https://github.com/tc39/proposals/blob/HEAD/finished-proposals.md

最后

以上就是寒冷电源最近收集整理的关于ECMA 2022 (es13) 新特性的全部内容,更多相关ECMA内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(53)

评论列表共有 0 条评论

立即
投稿
返回
顶部