JavaScript ES2020必知必會新特性

探索應用新技術能提高效率和下降成本。

1. Promise.allSettled

該方法接收一個可迭代的對象,例如Array,其中每一個成員都是Promise。僅在全部這些Promise狀態都改變爲rejectedresolved時,返回的promise的處理程序做爲輸入傳遞一個數組,每一個promise的結果包含status字符創,當statusfulfilled, 且返回一個value,反之,當statusrejected返回會包含一個reasonjavascript

const sleep = (timeout) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("sleep finish!");
    }, timeout);
  });
};
Promise.allSettled([
  sleep(2000),
  Promise.reject(new Error("error")),
]).then((res) => {
  console.log("res", res);
});

<img src="http://blog.toringo.cn/image-20200418222325629.png" alt="image-20200418222325629" style="zoom:50%;" />html

相關連接java

Promise.allSettled MDN文檔正則表達式

tc39npm

es-shims promise.allsettled數組

2. globalThis

ES2020 globalThis 提供了一個標準的方式來獲取不一樣環境下的全局 this 對象(也就是全局對象自身),因此不用擔憂運行環境。promise

globalThis.location === window.location; // true

globalThis MDN文檔瀏覽器

3. 可選鏈操做符 Optional Chaining

語法:?.babel

減小訪問深層對象時判斷屬性存不存在的問題。async

const adventurer = {
  name: 'Alice',
  cat: {
    name: 'Dinah'
  }
};
console.log(adventurer.dog?.name); 
// 輸出undefined; adventurer.dog?.name等價於adventurer.dog && adventurer.dog.name

console.log(adventurer.dog?.getName?.()); // undefined

// 短路計算
let potentiallyNullObj = null;
let x = 0;
let prop = potentiallyNullObj?.[x++];
console.log(x); // 做爲0的x將不會被遞增,依舊輸出0

注意: ?.不能用來賦值。

Optional Chaining MDN文檔

4. 空值合併運算符 Nullish Coalescing

空值合併運算符(??是一個邏輯運算符。當左側操做數爲 nullundefined 時,其返回右側的操做數。不然返回左側的操做數。

<img src="http://blog.toringo.cn/image-20200418230033414.png" style="zoom:50%;" />

同理能夠進行相似3 可選鏈操做符的短路操做。

Nullish Coalescing MDN文檔

5. import.meta

import.meta對象是由ECMAScript實現的,它帶有一個null的原型對象。這個對象能夠擴展,而且它的屬性都是可寫,可配置和可枚舉的。

<script type="module" src="index.js"></script>

// index.js
console.log(import.meta);
// 打印出{url: "http://127.0.0.1:8099/html/2020-JavaScript/index.js"}

React中使用參考babel插件babel-plugin-syntax-import-meta

import.meta MDN文檔

6. BigInt

之前JavaScript中存儲爲整數的最大數量爲pow(2, 53) - 1,ES2020 BigInt 是一種內置對象,它提供了一種方法來表示大於 253 - 1 的整數。BigInt 能夠表示任意大的整數。

BitInt是在整數後面添加n的方式定義,或者用BitInt(*);

<img src="http://blog.toringo.cn/1587265198006.jpg" alt="1587265198006" style="zoom:50%;" />

typeof 9007199254740991n === 'bigint'; // true
typeof BitInt('1') === 'bigint' // true;

注意:

  • 使用 Object 包裝後, BigInt 被認爲是一個普通 "object" :

    typeof Object(1n) === 'object'; // true
  • 當使用 BigInt 時,帶小數的運算會被取整。

    5n / 2n; // 2n
  • BigIntNumber 不是嚴格相等的,可是寬鬆相等的。

    1n === 1; // false;
    1n == 1; // true;
  • BigIntNumber 混在一個數組中能夠正常排序。
  • Object 包裝的 BigInts 使用 object 的比較規則進行比較,只用同一個對象在比較時纔會相等。

    0n === Object(0n); // false
    Object(0n) === Object(0n); // false
    const o = Object(0n);
    o === o // true
  • BigInt 在須要轉換成 Boolean 的時表現跟 Number 相似。
  • 因爲在 NumberBigInt 之間進行轉換會損失精度,於是建議僅在值可能大於253 時使用 BigInt 類型,而且不在兩種類型之間進行相互轉換。
  • 對任何 BigInt 值使用 JSON.stringify() 都會引起 TypeError,由於默認狀況下 BigInt 值不會在 JSON 中序列化。能夠手動實現:

    JSON.stringify(BigInt('0')); // Uncaught TypeError: Do not know how to serialize a BigInt
    BigInt.prototype.toJSON = function() { return this.toString(); }
    JSON.stringify(BigInt('0')); // '"0"'

BigInt MDN文檔

7. 動態導入 Dynamic Import

關鍵字import能夠像調用函數同樣來動態的導入模塊, 這種方式會返回一個promise

if(flag) {
  import('./module.js').then(fn => {
    fn.say();
  })
}
// 也能夠用async/await
if(flag) {
  const fn = await import('./module.js');
  fn.say();
}

Dynamic Import MDN文檔

8. 私有類變量 Private Class Variables

私有實例字段 是經過# names句型(讀做「哈希名稱」)聲明的,訪問和聲明時須要 帶着#。只能在內部使用。

class Cat {
  #name = 'tom';  
  getName() {
    console.log(this.#name);
  }
}

const cat = new Cat();
cat.getName(); // tom
cat.#name;  // Uncaught SyntaxError: Private field '#name' must be declared in an enclosing class

class Pig extends Cat {}
const pig = new Pig();
pig.getName(); // tom
pig.#name; // Uncaught SyntaxError: Private field '#name' must be declared in an enclosing class

私有實例方法, 語法相似都是#names

class ClassWithPrivateMethod {
  #privateMethod = () => {
    return "hello world";
  };

  getPrivateMessage() {
    return this.#privateMethod();
  }
}
const instance = new ClassWithPrivateMethod();
console.log(instance.getPrivateMessage()); // hello world

console.log(instance.#privateMethod()); // SyntaxError: Private field '#privateMethod' must be declared in an enclosing class

靜態私有字段

class ClassWithPrivateStaticField {
  static #PRIVATE_STATIC_FIELD;

  static publicStaticMethod() {
    ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD = 42;
    return ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD;
  }
}
console.log(
  ClassWithPrivateStaticField.publicStaticMethod() ===
    ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD
);

// SyntaxError: Private field '#PRIVATE_STATIC_FIELD' must be declared in an enclosing class

靜態私有方法

class ClassWithPrivateStaticMethod {
  static #privateStaticMethod = () => {
    return 42;
  };

  static publicStaticMethod() {
    return ClassWithPrivateStaticMethod.#privateStaticMethod();
  }
}

console.log(ClassWithPrivateStaticField.publicStaticMethod() === 42); // true

Private Class MDN文檔

9. String.prototype.matchAll

語法: str.matchAll(regexp)

給定一個字符串和一個正則表達式,matchAll()方法返回全部與該字符串匹配正則表達式的結果的迭代器,包括捕獲groups

let regexp = /t(e)(st(\d?))/g;
let str = 'test1test2';

let array = [...str.matchAll(regexp)];

console.log(array[0]); // ["test1", "e", "st1", "1"]

console.log(array[1]); // ["test2", "e", "st2", "2"]


let array2 = str.match(regexp);
console.log(array2); // [ 'test1', 'test2' ]

matchAll MDN文檔

10. For ... in 定義了明確的順序

ECMA規範未指定for (x in y) 應按哪一個順序運行。即便之前瀏覽器本身實現了一致的順序,但ES2020已正式對其進行標準化。

11. 模塊名稱空間導出 Module namespace exports

JavaScript中可使用一下語法:

import * as utils from './module.js';
// 可是,不export存在對稱語法, 可是如今已支持
export * as utils from './module.js';
// 等效於
import * as utils from './utils.mjs';
export { utils };

歡迎留言指正,或羅列更多的ES新特性。


參考文章

相關文章
相關標籤/搜索