JavaScript ES2020必知必會新特性
編者按:本文作者奇舞團前端工程師郭文濤。
#1. Promise.allSettled
該方法接收一個可迭代的對象,例如Array,其中每個成員都是Promise。僅在所有這些Promise狀態(tài)都改變?yōu)?span style="margin-right: 2px;margin-left: 2px;border-width: 1px;border-style: solid;border-color: rgb(225, 225, 232);padding: 2px 4px;font-size: 12px;font-family: monospace;color: rgb(221, 17, 68);background-color: rgb(247, 247, 249);border-radius: 2px;word-break: break-all;overflow-wrap: break-word;hyphens: auto;">rejected或resolved時,返回的promise的處理程序作為輸入傳遞一個數(shù)組,每個promise的結果包含status字符創(chuàng),當status為fulfilled, 且返回一個value,反之,當status為rejected返回會包含一個reason。
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);
});
相關鏈接
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled
https://tc39.es/proposal-promise-allSettled/
https://www.npmjs.com/package/promise.allsettled
#2. globalThis
ES2020 globalThis 提供了一個標準的方式來獲取不同環(huán)境下的全局 this 對象(也就是全局對象自身),所以不用擔心運行環(huán)境。
globalThis.location?===?window.location;?// true
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/globalThis
#3.?可選鏈操作符 Optional Chaining
語法:?.
減少訪問深層對象時判斷屬性存不存在的問題。
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
注意: ??.不能用來賦值。
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/可選鏈
#4. 空值合并運算符 Nullish Coalescing
空值合并運算符(??)是一個邏輯運算符。當左側操作數(shù)為 null 或 undefined 時,其返回右側的操作數(shù)。否則返回左側的操作數(shù)。
同理可以進行類似3 可選鏈操作符的短路操作。
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator
#5. import.meta
import.meta對象是由ECMAScript實現(xiàn)的,它帶有一個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。
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/import.meta
#6. BigInt
以前JavaScript中存儲為整數(shù)的最大數(shù)量為pow(2, 53) - 1,ES2020 BigInt 是一種內置對象,它提供了一種方法來表示大于 253 - 1 的整數(shù)。BigInt 可以表示任意大的整數(shù)。
BitInt是在整數(shù)后面添加n的方式定義,或者用BitInt(*);
typeof?9007199254740991n?===?'bigint';?// true
typeof?BitInt('1')?===?'bigint'?// true;
注意:
使用 Object 包裝后, BigInt 被認為是一個普通 "object" :
typeof?Object(1n)?===?'object';?// true
當使用 BigInt 時,帶小數(shù)的運算會被取整。
5n?/?2n;?// 2n
BigInt 和 Number 不是嚴格相等的,但是寬松相等的。
1n?===?1;?// false;
1n?==?1;?// true;
BigInt 和 Number 混在一個數(shù)組中可以正常排序。
Object 包裝的 BigInts 使用 object 的比較規(guī)則進行比較,只用同一個對象在比較時才會相等。
0n?===?Object(0n);?// false
Object(0n)?===?Object(0n);?// false
const?o?=?Object(0n);
o?===?o?// true
BigInt 在需要轉換成 Boolean 的時表現(xiàn)跟 Number 類似。
由于在 Number 與 BigInt 之間進行轉換會損失精度,因而建議僅在值可能大于253 時使用 BigInt 類型,并且不在兩種類型之間進行相互轉換。
對任何 BigInt 值使用 JSON.stringify() 都會引發(fā) TypeError,因為默認情況下 BigInt 值不會在 JSON 中序列化。可以手動實現(xiàn):
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"'
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/BigInt
#7. 動態(tài)導入 Dynamic Import
關鍵字import可以像調用函數(shù)一樣來動態(tài)的導入模塊, 這種方式會返回一個promise。
if(flag)?{
import('./module.js').then(fn?=>?{
fn.say();
})
}
// 也可以用async/await
if(flag)?{
const?fn?=?await?import('./module.js');
fn.say();
}
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/import
#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
靜態(tài)私有字段
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
靜態(tài)私有方法
class?ClassWithPrivateStaticMethod?{
static?#privateStaticMethod?=?()?=>?{
return?42;
};
static?publicStaticMethod()?{
return?ClassWithPrivateStaticMethod.#privateStaticMethod();
}
}
console.log(ClassWithPrivateStaticField.publicStaticMethod()?===?42);?// true
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes/Class_elements
#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' ]
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/matchAll
#10. For ... in 定義了明確的順序
ECMA規(guī)范未指定for (x in y) 應按哪個順序運行。即使以前瀏覽器自己實現(xiàn)了一致的順序,但ES2020已正式對其進行標準化。
#11. 模塊名稱空間導出 Module namespace exports
在JavaScript中可以使用一下語法:
import?*?as?utils?from?'./module.js';
// 但是,不export存在對稱語法, 但是現(xiàn)在已支持
export?*?as?utils?from?'./module.js';
// 等效于
import?*?as?utils?from?'./utils.mjs';
export?{?utils?};
歡迎留言指正,或羅列更多的ES新特性。
參考文章
https://v8.dev/features/tags/es2020
https://developer.mozilla.org/zh-CN
最后
如果你覺得這篇內容對你挺有啟發(fā),我想邀請你幫我三個小忙:
點個「在看」,讓更多的人也能看到這篇內容(喜歡不點在看,都是耍流氓 -_-)
歡迎加我微信「qianyu443033099」拉你進技術群,長期交流學習...
關注公眾號「前端下午茶」,持續(xù)為你推送精選好文,也可以加我為好友,隨時聊騷。






