ECMASCRIPT 2021新功能代码演示案例


在这篇文章中,我们将通过代码示例探索一些最近发布的 ECMAScript 2021 功能的用例。
ECMAScript 是构成 JavaScript 基础的脚本语言。
新功能:

  1. String.prototype.ReplaceAll()
  2. 弱引用
  3. Finalization注册
  4. Promise.any()
  5. AggregateError 
  6. 逻辑赋值运算符
  7. 数字文字的分隔符

 

String.prototype.ReplaceAll()
用例:
这个新功能可以替换字符串中子字符串的每个实例。这与旧的 String.prototype.Replace() 不同,后者仅替换子字符串的第一次出现。

//with replace()

const replaceMethodEg =
"I felt happy because I saw the others were happy and because I knew I should feel happy";

console.log(replaceMethodEg.replace(
"happy", "sad"));
// Output: I felt sad because I saw the others were happy and because I knew I should feel happy.


//with replaceAll()

const replaceAllMethodEg =
"I felt happy because I saw the others were happy and because I knew I should feel happy";

console.log(replaceAllMethodEg.replaceAll(
"happy", "sad"));
// Output: I felt sad because I saw the others were sad and because I knew I should feel sad.

 
弱引用
WeakRef 允许您创建对对象的弱引用,而不会阻止 JavaScript 引擎的垃圾收集器回收该对象。对对象的正常(强)引用将对象保存在内存中并防止对象被垃圾收集器销毁。当一个对象不再有任何强引用时,JavaScript 引擎的垃圾收集器可能会销毁该对象并回收其内存。如果发生这种情况,您将无法再从弱引用中获取对象。
用例:
弱引用的主要用途是实现保存大对象的缓存或映射,在这种情况下,希望大对象不会仅仅因为它出现在缓存或映射中而保持活动状态

// An object to reference weakly

const objToRef = { name:
"Queen", age: 23, favColor: 'purple' };

// creating a WeakRef of this object

const weakRefObj = new WeakRef(objToRef);

读取WeakRefs的值,使用deref()方法返回实例

// create an Instance

const weakRefInstance = weakRefObj.deref();

console.log(weakRefInstance.age)

// Output: 23

警告:由于垃圾收集器的复杂/不可预测性,不建议创建 WeakRef。垃圾收集何时、如何以及是否发生取决于任何给定 JavaScript 引擎的实现。在一个引擎中观察到的任何行为都可能与另一个引擎不同。
 
Finalization Registry
Finalization 是在程序执行无法访问的对象之后执行代码以进行清理。
用例:
与 WeakRef 一起引入的 Finalization Registry 用于管理在目标对象被垃圾收集时执行的清理操作的注册和注销。清理回调有时称为终结器。

// create a registry

const registry = new FinalizationRegistry(heldValue => {
    // Do something here

});

//您可以通过调用该register()方法、传入对象和为其保留的值来注册您想要清除回调的任何对象:

registry.register(theObject, "some value");

传递给register()方法的对象将是弱引用,因此当该值被垃圾收集时,第二个参数(“某个值”)将传递给终结器。
警告:就像 WeakRefs 一样,FinalizationRegistry 应该避免使用,并且只有在仔细考虑后才能使用,原因与上述相同。
  
Promise.any()
Promise.any() 接受一个可迭代的承诺对象,并在可迭代对象中的一个承诺满足时进行解析。这与旧的 promise.all() 不同,它在解决之前等待所有承诺解决。它在一个承诺完成后短路,所以一旦找到一个承诺,它就不会等待其他承诺完成。如果我们只需要兑现一个承诺,但我们不关心哪一个兑现,这可能是有益的。

// demonstrating promise.any()

const firstPromise = new Promise((resolve) => setTimeout(resolve, 700, 'I am the first promise'));

const secondPromise = new Promise((resolve) => setTimeout(resolve, 300, 'I am the second promise'));

const thirdPromise = new Promise((resolve) => setTimeout(resolve, 1000, 'I am the third promise'));

const allPromises = [firstPromise, secondPromise, thirdPromise];

Promise.any(allPromises)
    .then((value) => console.log(value)) 

// Output: "I am the second promise"

 
AggregateError  
AggregateError 对象表示将单个错误组合在一起的错误。当一个操作需要报告多个错误时抛出。
用例:
以上面的promise.any()方法代码为例,如果所有的promise都拒绝了,就会抛出一个聚合错误。

// demonstrating AggregateError

const rejectedPromise = Promise.reject(new Error(
"an error"));

Promise.any([rejectedPromise])
    .catch(e => {
        console.log(e instanceof AggregateError);
// Output: true
        console.log(e);  
// Output: AggregateError: All promises were rejected
    });

 
逻辑赋值运算符
这是逻辑运算(&&, || or ??)与赋值运算符(=)的组合。即||=, &&=, ??=。

用例:
逻辑 OR 赋值运算符x ||= y仅在 x 为假时赋值

// Logical OR assignment operator (||=)

let myName = '';
let myGrade = 5;

myName ||= 'Obi';

console.log(myName);
// Output: "Obi"

myGrade ||= 2;

console.log(myGrade);
// Output: 5

// Logical AND assignment (&&=)

let a = 1;

a &&= 3
// Output: a = 3

// Logical nullish assignment (??=)

let a;

let b = 50;

a ??= b;

console.log(a);
//Output: 50

 
数字文字的分隔符
用例:
引入这些分隔符是为了使开发人员能够通过在数字组之间创建视觉分隔来使数字文字更具可读性。大数字文字很难在视觉上解析,特别是当有很长的数字重复时。

1000000000 // Is this a billion? a hundred million? Ten millions? 101475938.38 // what scale is this? what power of 10?

常规数字文字:
let budget = 1_000_000_000_000;
// What is the value of `budget`? It's 1 trillion!
// 
// Let's confirm:
console.log(budget === 10 ** 12);
// true

二进制文字
let nibbles = 0b1010_0001_1000_0101;

// Is bit 7 on? It sure is!
// 0b1010_0001_1000_0101
//           ^
//
// We can double check: 
console.log(!!(nibbles & (1 << 7)));
// true

十六进制文字:
// Messages are sent as 24 bit values, but should be 
// treated as 3 distinct bytes:
let message = 0xA0_B0_C0;

// What's the value of the upper most byte? It's A0, or 160.
// We can confirm that:
let a = (message >> 16) & 0xFF;
console.log(a.toString(16), a);
// a0, 160

// What's the value of the middle byte? It's B0, or 176.
// Let's just make sure...
let b = (message >> 8) & 0xFF;
console.log(b.toString(16), b);
// b0, 176

// What's the value of the lower most byte? It's C0, or 192.
// Again, let's prove that:
let c = message & 0xFF;
console.log(c.toString(16), b);
// c0, 192