js es2021(es12):新特性

2,541 阅读6分钟

betterprogramming.pub/javascript-…

image.png

新的 ES12 规范终于来了,规范?JavaScript 确实不是一种开源语言,它是一种遵循 ECMAScript 标准规范编写的语言。TC39 委员会负责讨论和批准新功能。他们是谁?

“ECMA International 的 TC39 是一组 JavaScript 开发人员、实施人员、学者等,他们与社区合作维护和发展 JavaScript 的定义。” — TC39.es

它们的发布过程由五个阶段组成。自 2015 年以来,他们一直在进行年度发布。它们通常发生在春天左右。下一个提案的批准日期是 6 月。

有两种方法可以引用任何 ECMAScript 版本:

1)到它的年份:这个新版本将是 ES2021

2)通过迭代次数:这个新版本将是第 12 次迭代,因此它可以被称为 ES12。

那么这个版本有什么新东西呢?我们可以对哪些功能感到兴奋?

replaceAll

String 原型中添加了一个新函数。在此添加之前,不使用正则表达式不可能替换子字符串的所有实例。

ES12 之前:

// using Regex to replace
'1 2 1 2 1 2'.replace(new RegExp('2', 'g'), '0');
// another option
'1 2 1 2 1 2'.replace(/2/g, '0');

// we can create our own helper
function replaceAll(str, find, replace) {
 return str.replace(new RegExp(find, 'g'), replace);
}

现在:

'1 2 1 2 1 2'.replaceAll('2', '0');

如果搜索参数是空字符串会发生什么?它将返回每个 UCS-2/UTF-16 代码单元之间的替换值。

'x'.replace('', '_');
// '_x''xxx'.replace(/(?:)/g, '_');
// '_x_x_x_''xxx'.replaceAll('', '_');
// '_x_x_x_'

互联网上有很多关于这个主题的问题。因此,我们可以推断这将是一个有用的功能。不需要任何正则表达式知识使其更易于访问。

Promise.any

新的 Promise.any 方法是另一个有用的工具。它需要一个可迭代的 promise 作为参数.当其中任何一个完成时,它将触发 Promise.any() 参数回调或返回响应。这取决于您是否使用 async/await。

如果所有的 Promise 都失败了,该方法将抛出一个 AggregateError,它结合了所有不同的 Promise 错误。什么不返回一个普通数组?主要是为了兼容性。它将是 Error 的一个实例,您将获得堆栈跟踪。如果需要,最好有这些信息。

让我们看一些例子。

  • 使用传统的 callback 语法:
Promise.any([
    Promise.reject('Error 1'),
    Promise.reject('Error 2'),
    Promise.resolve('success'),
]).then((result) => {
    console.log('result:', result);
});
// result: success
  • 使用 async/await 语法:
(async () => {
    const result = await Promise.any([
        Promise.reject('Error 1'),
        Promise.reject('Error 2'),
        Promise.resolve('success'),
    ]);
    console.log(`result: ${result}`);
})();
// result: success

让我们检查一个错误示例场景:

(async () => {
    try {
        const result = await Promise.any([
            Promise.reject('Error 1'),
            Promise.reject('Error 2'),
            Promise.reject('Error 3'),
        ]);
        console.log(`result ${result}`);
    } catch (err) {
        console.log(`error: ${err.errors}`);
    }
})();
// error: Error 1,Error 2,Error 3

这是对 Promise 原型的第四次添加。快速回顾一下,目前,我们可以使用以下内容:

  • [ES2020] Promise.allSettled: This method returns a promise that resolves when all the given promises have either been fulfilled or rejected. The returned object describes each individual promise result.

  • [ES2015] Promise.all: This method returns a promise that is fulfilled only if all the target promises were fulfilled.

  • [ES2015] Promise.race: This method will return a promise that will be fulfilled as soon as one of the promises is either rejected or fulfilled.

WeakRefs

JavaScript 有一个自动垃圾收集过程。它只能收集无法访问的对象。每次对一个对象进行赋值时,都是在创建一个这可以保护它免受垃圾收集,这可以保护它免受垃圾收集

// x is a strong reference to the object\
const x = { foo: 'bar' };

WeakRef服务于一个完全不同的用例:持有对不会保护它免受垃圾收集的对象的引用。由于垃圾收集是非确定性的,因此无法真正保证何时清除对象,甚至是否会清除。WeakRef通过让您访问该对象直到它被收集来利用这一点。

WeakRef只能将对象作为参数。

function Foo() {}// strong reference to a Foo instance
const x = new Foo();// weak reference to the Foo's instance
const xWeak = new WeakRef(x);

如何取回这个值,使用deref(),请记住,该方法将返回对对象的强引用。

function Foo() {}

// strong reference to a Foo instance
const x = new Foo();

// weak reference to the Foo's instance
const xWeak = new WeakRef(x);

// strong reference to the Foo's instance
const xFromWeak = xWeak.deref();

为什么这很有用?它可以让您根据用户的设备提高应用程序的性能。我们可以用WeakRef缓存大对象,意味着具有更多内存的机器可以看到应用程序性能的提高。那些内存有限的人仍然可以在不消耗用户内存的情况下工作。

Finalizers

Finalizers是内存区域中的另一个 ES12 特性。此功能的作用是让您知道对象何时被垃圾收集。它通过 JavaScript 回调来实现。

但是,有几点需要牢记:

  • 不保证回调会执行。

  • 目标对象已经被清理,将无法访问。

  • 回调将执行多长时间是不确定的。它可以是一分钟或一小时。

// object creation
let x = new Array(1000).fill(true);

// constructing the finalizer method
const cleanup = new FinalizationRegistry(key => {
  // cleanup code should go here
});

// hooking the x variable to the finalizer
cleanup.register(x, 'fsdfs');

// object 'x' is now unreachable, finalizer callback might happen after
// object has been garbage collected
x = null;

此功能使您有机会进行进一步的清理以帮助优化您的应用程序。

注意:这不是您想要运行关键代码的地方。这是一个旨在帮助进一步减少我们的内存 Web 应用程序占用空间的地方。

Logical Assignment Operators

最后,这些新的 ES12 规范附带了期待已久的运算符。新运算符将逻辑赋值运算符与逻辑运算结合起来&& ,||, and ??

Operator &&=

让我们将其在 ES11 中的等效项与新规范进行比较。

之前:

x && (x = y)

之后:

x &&= y;

例子:

let x = 5;
const y = 10;
x &&= y;

console.log(x);
// result is 10

Operator ||=

让我们将其在 ES11 中的等效项与新规范进行比较。

之前:

x || (x = y)

之后:

x ||= y;

例子:

let x = 5;
const y = 10;
x ||= y;

console.log(x);
// result is 5

Operator ??=

?? 是 JavaScript 的空合并运算符。让我们回顾一下它的作用,因为它不太常见。

空合并运算符 (??) 是一个逻辑运算符,当其左侧操作数为空或未定义时返回其右侧操作数,否则返回其左侧操作数。” — MDN 网络文档

之前:

x ?? (x = y);

之后:

x ??= y;

例子:

let x;
const y = 10;
x ??= y;

console.log(x);
// result is 10

Numeric Separators

这种添加可能不那么花哨,但它确实有助于提高代码的可读性。目前,当在 var/let/const 变量中存储长数时,它可能不可读。

让我们看一个例子。让我们创建一个常数 100 万。很明显,长数字很难阅读。

const oneMillion = 1000000;

使用新的 ES12 语法,您可以使用 _ 字符在数字之间创建分隔。

const oneMillion = 1_000_000;

它可用于二进制和十六进制文字:

const max8bits = 0b1111_1111;const message = 0xA0_B0_C0;

这绝对是我会经常使用的东西。