JavaScript ES 2021(ES12)新功能

内容简介

  • 逻辑赋值运算符(明雪讲过:https://cc.komect.com/website/blog/detail?id=296 关键词:运算符)
  • 数字分隔符
  • Promise.any() (Promise拓展)
  • replaceAll

逻辑赋值运算符

1. 前置知识点:

运算符优先级
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Operator_Precedence

falsy值 (虚值):https://developer.mozilla.org/zh-CN/docs/Glossary/Falsy
这意味着当 JavaScript 期望一个布尔值,并被给与下面值中的一个时,它总是会被当做 false。

es12-1.jpg
if (false)
if (null)
if (undefined)
if (0)
if (0n)
if (NaN)
if ('')
if ("")
if (``)
if (document.all) //document.all 虽然是一个对象,但其转换为 boolean 类型是 false

空值合并运算符:空值合并操作符??)是一个逻辑操作符,当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数。

2. 定义

逻辑赋值操作符将逻辑操作(&&、||或??)与赋值表达式组合在一起。

现有的的运算符,其工作方式都可以如此来理解
表达式:a op= b
等同于:a = a op b
例如:a+=b a=a+b

逻辑赋值运算符则按照下面的方式理解

x ||= y;
x || (x = y);  // x 为 falsy 则 x=y

x &&= y;
x && (x = y); // x 为 真值 则 x=y

x ??= y;
x ?? (x = y); // x 为 null或undefined 则 x=y

3. 应用

适用于赋值默认值的场景


数字分隔符

1. 定义

数字分隔符,可以在数字之间创建可视化分隔符,通过_下划线来分割数字,使数字更具可读性

const num = 1_000_000;
console.log(num); //1000000

分隔符可以用于数字的整数部分和小数部分。分隔符不仅可以用在整数和浮点数中,也可以用在二进制、十六进制、八进制字面量中。分隔符也适用于BigInt数字。

2. 应用

增加代码可读性,方便读取数据


Promise.any()

1. 前置知识点:

Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。

Promise.all 全部resolve回调结束或者任意一个reject。

Promise.allSettled 返回一个在所有给定的promise都已经fulfilled或rejected后的promise,并带有一个对象数组,每个对象表示对应的promise结果。

总结:
allSettled:当您有多个彼此不依赖的异步任务成功完成时,或者您总是想知道每个promise的结果时
all:彼此相互依赖或者在其中任何一个reject时立即结束

2. 定义

Promise.any() 接收一个Promise可迭代对象,只要其中的一个 promise 成功,就返回那个已经成功的 promise 。如果可迭代对象中没有一个 promise 成功(即所有的 promises 都失败/拒绝),就返回一个失败的 promiseAggregateError类型的实例,它是 Error 的一个子类,用于把单一的错误集合在一起。

与race对比示例

const pErr = new Promise((resolve, reject) => {
  reject("总是失败");
});

const pSlow = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, "最终完成");
});

const pFast = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, "很快完成");
});

Promise.any([pErr, pSlow, pFast]).then((value) => {
  console.log(value);
  // pFast fulfils first
})
// 期望输出: "很快完成"

Promise.race([pErr, pSlow, pFast]).then((value) => {
  console.log(value);
  // pErr rejected first
})
// 期望输出: "总是失败"

AggregateError异常示例

const pErr = new Promise((resolve, reject) => {
  reject('总是失败');
});

Promise.any([pErr]).catch((err) => {
  console.log(err);
})
// 期望输出: "AggregateError: All promises were rejected"

3. 应用

显示第一张已加载的图片,我们有一个获取图片并返回 blob 的函数,我们使用 Promise.any() 来获取一些图片并显示第一张有效的图片(即最先 resolved 的那个 promise)。

4. 扩展 (Promise时间线)

Promise:ES6(2015)
Promise.finally():ES9(2018)
在promise结束时,无论结果是fulfilled或者是rejected,都会执行指定的回调函数。这为在Promise是否成功完成后都需要执行的代码提供了一种方式。这避免了同样的语句需要在then()catch()中各写一次的情况。
Promise.allSettled:ES11(2020)
Promise.any:ES12(2021)


String.prototype.replaceAll

1. 定义

replaceAll() 方法返回一个新字符串,新字符串所有满足 pattern 的部分都已被replacement 替换。pattern可以是一个字符串或一个 RegExpreplacement可以是一个字符串或一个在每次匹配被调用的函数。

!!!可以不用正则匹配去全局替换了

const str = "Backbencher sits at the Back";
const newStr = str.replace("Back", "Front");
console.log(newStr); // "Frontbencher sits at the Back"

const str = "Backbencher sits at the Back";
const newStr = str.replace(/Back/g, "Front");
console.log(newStr); // "Frontbencher sits at the Front"

const str = "Backbencher sits at the Back";
const newStr = str.replaceAll("Back", "Front");
console.log(newStr); // "Frontbencher sits at the Front"

const str = "Backbencher sits at the Back";
const newStr = str.replaceAll(/Back/g, "Front");
console.log(newStr); // "Frontbencher sits at the Front"

WeakRef

1. 前置知识点

垃圾回收机制 https://cc.komect.com/website/blog/detail?id=216 (珊珊讲过 关键词:垃圾回收)
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Memory_Management

WeakSet对象允许你将弱保持对象存储在一个集合中。

弱引用Set。只能存储对象,不能存储其他类型。且只保持对其中对象的弱引用,若外部无对此对象的引用,或者对象被删除,则WeakSet中将不再有此对象。
因为成员都是弱引用,随时可能消失,遍历不能保证成员的存在。所以 WeakSet 不能遍历。

WeakMap 对象是一组键/值对的集合,其中的键是弱引用的。其键必须是对象,而值可以是任意的。

相比之下,原生的 WeakMap 持有的是每个键对象的“弱引用”,这意味着在没有其他引用存在时垃圾回收能正确进行。原生 WeakMap 的结构是特殊且有效的,其用于映射的 key 只有在其没有被回收时才是有效的。
正由于这样的弱引用,WeakMap 的 key 是不可枚举的 (没有方法能给出所有的 key)。如果key 是可枚举的话,其列表将会受垃圾回收机制的影响,从而得到不确定的结果。因此,如果你想要这种类型对象的 key 值的列表,你应该使用 Map

WeakMap和WeakSet的作用,可以用来存储DOM节点,保持与DOM节点相关的数据,当DOM节点被删除后,集合中的数据自动删除,
这样就不必担心移除DOM节点时的内存泄漏了。

2. 定义

WeakRef对象允许您保留对另一个对象的弱引用,而不会阻止被弱引用对象被GC回收

弱引用的主要用途是实现大型对象的缓存或映射。在这种情况下,我们不希望长期保留大量的内存来保存这种很少使用的缓存或映射。我们可以让内存很快被垃圾回收,以后如果我们再次需要它,我们可以生成一个新的缓存。
在一个DOM元素中启动一个计数器,当这个元素不存在时停止。

class Counter {
  constructor(element) {
    // Remember a weak reference to the DOM element
    this.ref = new WeakRef(element);
    this.start();
  }

  start() {
    if (this.timer) {
      return;
    }

    this.count = 0;

    const tick = () => {
      // Get the element from the weak reference, if it still exists
      const element = this.ref.deref();
      if (element) {
        element.textContent = ++this.count;
      } else {
        // The element doesn't exist anymore
        console.log("The element is gone.");
        this.stop();
        this.ref = null;
      }
    };

    tick();
    this.timer = setInterval(tick, 1000);
  }

  stop() {
    if (this.timer) {
      clearInterval(this.timer);
      this.timer = 0;
    }
  }
}

const counter = new Counter(document.getElementById("counter"));
counter.start();
setTimeout(() => {
  document.getElementById("counter").remove();
}, 5000);
  • 尽量避免使用
    正确使用WeakRef对象需要仔细的考虑,最好尽量避免使用。避免依赖于规范没有保证的任何特定行为也是十分重要的。何时、如何以及是否发生垃圾回收取决于任何给定JavaScript引擎的实现。GC在一个JavaScript引擎中的行为有可能在另一个JavaScript引擎中的行为大相径庭,或者甚至在同一类引擎,不同版本中GC的行为都有可能有较大的差距。GC目前还是JavaScript引擎实现者不断改进和改进解决方案的一个难题。

babel

https://babeljs.io/docs/en/babel-plugin-proposal-logical-assignment-operators
https://babeljs.io/docs/en/babel-plugin-proposal-numeric-separator


参考文章
https://www.ahwgs.cn/lingrenxingfendesandaxinjavascript-es-2021es-12gongneng.html
https://blog.csdn.net/pz1021/article/details/115242973
https://mp.weixin.qq.com/s/tZ5pnyl1R-7Q60-QHtb-jw
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/WeakRef

你可能感兴趣的:(JavaScript ES 2021(ES12)新功能)