ECMAScript 2020新增特性

前言

TC39 委員會(huì)于近期批準(zhǔn)了 ECMAScript 2020(即 ES2020)候選提案轻黑,即經(jīng)審定最終添加到 JavaScript 語(yǔ)言中的特性集炮温。ES2020 候選提案是今年六月提交 ECMA 大會(huì)(General Assembly)的審批匯總。

1. Promise.allSettled

Promise.all 缺陷

都知道 Promise.all 具有并發(fā)執(zhí)行異步任務(wù)的能力贵少。

先復(fù)習(xí)一下Promise.all 的用法

let p1 = Promise.resolve({
    code: 200,
    list: ["數(shù)據(jù)1"]
})
let p2 = Promise.resolve({
    code: 200,
    list: ["數(shù)據(jù)2"]
})
let p3 = Promise.resolve({
    code: 200,
    list: ["數(shù)據(jù)3"]
})

Promise.all([p1,p2,p3]).then((result) => {
    // all方法并發(fā)的三個(gè)promise都是成功狀態(tài)會(huì)執(zhí)行
    console.log(result);
    /*
        返回的結(jié)果: [{…}, {…}, {…}]
    */
}).catch((error) => {
    console.log(error);
})


但時(shí)Promise.all 方法最大問(wèn)題就是如果其中某個(gè)任務(wù)出現(xiàn)異常(reject),所有任務(wù)都會(huì)掛掉,Promise直接進(jìn)入 reject 狀態(tài)糜烹。

let p1 = Promise.resolve({
      code: 200,
      list: ["數(shù)據(jù)2"]
  })
  let p2 = Promise.reject({
      code: 500,
      errorMsg:"服務(wù)器錯(cuò)誤"
  })

  let p3 = Promise.resolve({
      code: 200,
      list: ["數(shù)據(jù)3"]
  })

  Promise.all([p1,p2,p3]).then((result) => {
     // 如果有一個(gè)promise 是reject,則不會(huì)執(zhí)行這個(gè)回調(diào)函數(shù)
      console.log(result);   
  }).catch((error) => {
      console.log(error);
      // 因?yàn)閜2 是reject 所以會(huì)執(zhí)行這個(gè)回到函數(shù)
      // {code: 500,errorMsg:"服務(wù)器錯(cuò)誤"}
  })

如果小伙伴們?cè)跍y(cè)試代碼的時(shí)候,記得重新打開(kāi)頁(yè)面,不要刷新.

想象這個(gè)場(chǎng)景:在你的項(xiàng)目中,使用 Promise.all 來(lái)并發(fā)三個(gè)接口,每個(gè)接口都單獨(dú)對(duì)應(yīng)一個(gè)接口,請(qǐng)求數(shù)據(jù), 如果其中任意一個(gè)接口服務(wù)異常漱凝,狀態(tài)是reject,這會(huì)導(dǎo)致三個(gè)區(qū)域數(shù)據(jù)全都無(wú)法渲染出來(lái)疮蹦,因?yàn)槿魏?reject 都會(huì)進(jìn)入catch回調(diào), 很明顯,這是無(wú)法接受的.

Promise 在 ES2020 中新增了 Promise.allSettled() 茸炒,就能好的 幫我們解決這個(gè)問(wèn)題,Promise.allSetted 方法,無(wú)論一個(gè)任務(wù)是正炽岛酰或是異常,都會(huì)返回對(duì)應(yīng)的狀態(tài)(fulfilled或者rejected)與結(jié)果(value),

let p1 = Promise.resolve({
    code: 200,
    list: ["數(shù)據(jù)2"]
})
let p2 = Promise.reject({
    code: 500,
    errorMsg:"服務(wù)器錯(cuò)誤"
})

let p3 = Promise.resolve({
    code: 200,
    list: ["數(shù)據(jù)3"]
})

Promise.allSettled([p1,p2,p3]).then((result) => {
            // Promise.allSettled會(huì)在這里中處理并發(fā)promise狀態(tài)和結(jié)果
    console.log(result);
    /**
                返回的結(jié)果:
               [
                 {status: "fulfilled", value: {…}}
                 {status: "rejected", reason: {…}}
                 {status: "fulfilled", value: {…}}
               ]
            */

})

這樣我們?cè)趖hen方法中得到所有結(jié)果以后,我們就可以使用fill來(lái)過(guò)濾狀態(tài)為rejected掉的數(shù)據(jù)

2. String.prototype.matchAll


String.prototype上的match()方法僅返回完全匹配,但是沒(méi)有返回關(guān)于特定正則組的任意信息壁公。String.prototype.matchAll可以返回比match()多很多的信息感论。返回的迭代器除了精確匹配外還給了我們?cè)L問(wèn)所有的正則匹配捕獲組。

還節(jié)的match方法嗎?看下面一段代碼

let str = "<div>this is div</div><p>this is JS</p>";
let reg = /<\w+>(.*?)<\/\w+>/g;
console.log(str.match(reg));
/**
  返回結(jié)果:
     ["<div>this is div</div>", "<p>this is JS</p>"]
*/

我們都知道紊册,match是可以正常匹配到所有匹配項(xiàng)比肄,但卻沒(méi)辦法匹配到子項(xiàng)(group)。如果想要匹配子項(xiàng)囊陡,那么需要把全局匹配 /g 標(biāo)識(shí)去掉芳绩。

let str = "<div>this is div</div><p>this is JS</p>";
let reg = /<\w+>(.*?)<\/\w+>/;
console.log(str.match(reg));
/**
 [
    0: "<div>this is div</div>"
    1: "this is div"
    groups: undefined
    index: 0
    input: "<div>this is div</div><p>this is JS</p>"
    length: 2
  ]
**/  

這樣可以獲取到匹配的父項(xiàng),包括子項(xiàng)(group)撞反,但只能獲取到第一個(gè)滿足的匹配字符妥色。

如果既想要匹配所有匹配項(xiàng),又想要匹配子項(xiàng)遏片,那么 match() 是無(wú)法滿足的嘹害。ES2020 提供了 matchAll() 方法.

注意matchAll方法返回的是迭代器,因此我們需要遍歷獲取結(jié)果

let str = '<div>this is div</div><p>this is JS</p>';
let reg = /<\w+>(.*?)<\/\w+>/g;
let allMatchs = str.matchAll(reg);

for(let match of allMatchs){
    console.log(match)
}
/**
  第一次遍歷的結(jié)果:
    [
      0: "<div>this is div</div>"
      1: "this is div"
      groups: undefined
      index: 0
      input: "<div>this is div</div><p>this is JS</p>"
      length: 2
    ]
  第二次遍歷的結(jié)果:
    [
      0: "<p>this is JS</p>"
      1: "this is JS"
      groups: undefined
      index: 22
      input: "<div>this is div</div><p>this is JS</p>"
      length: 2
    ]
**/

3. import()


目前前端項(xiàng)目打包的資源越來(lái)越大鳍侣,但應(yīng)用初始化時(shí)資源并不需要全量加載,為了提高頁(yè)面性能吼拥,往往需要按需加載資源倚聚。Domenic Denicola提案的動(dòng)態(tài)導(dǎo)入可以實(shí)現(xiàn)按需加載。這個(gè)類似函數(shù)的格式(不是繼承自Function .prototype)返回一個(gè)很強(qiáng)大的promise凿可。使用場(chǎng)景比如: 按需導(dǎo)入惑折,在一個(gè)腳本中計(jì)算模塊名并加載執(zhí)行變得可能。

element.onclick = () =>{
   import("/js/helpers.js")
    .then((module) =>{
        console.log(module)
    })
    .chatch((err) => {
        // load err
        console.log(err)
    })
}

因此我們也可以使用async異步函數(shù)來(lái)配置處理

element.onclick = async () =>{
   let module = await import("/js/helpers.js")
   // 處理 導(dǎo)入module模塊
}

4. BigInt


JavaScript 中 Number 類型都保存為 64 位浮點(diǎn)數(shù)枯跑,精確度只能到 53 位,也就是說(shuō)Js 中 Number類型只能安全的表示-(2^53-1)至 2^53-1 范的值惨驶,超出這個(gè)范圍的整數(shù)計(jì)算或者表示會(huì)丟失精度。

console.log(Math.pow(2, 53));   // 9007199254740992
console.log(Math.pow(2, 53) + 1);  // 9007199254740992
console.log(Math.pow(2, 53) === Math.pow(2, 53) + 1); // true

且無(wú)法正確表示大于或等于 2^1024 的數(shù)值敛助。

console.log(Math.pow(2, 1023));  // 8.98846567431158e+307
console.log(Math.pow(2, 1024));  // Infinity

ES2020 中引入了新的數(shù)據(jù)類型 BigInt, 讓Number.MAXSAFEINTEGER不再是JavaScript中的一個(gè)限制粗卜。BigInt是一個(gè)能表示任意精度整數(shù)的新基礎(chǔ)類型。你可以通過(guò)使用BigInt方法或者在一個(gè)數(shù)字后添加n后綴來(lái)把一個(gè)數(shù)字轉(zhuǎn)換為一個(gè)新的bigint類型纳击。

// 使用BigInt
// 1\. 字面量方式在數(shù)字字面量后面加n
let num = 123n;
console.log(num);   // 123n
console.log(typeof num); // bigint

// 2\. 函數(shù)執(zhí)行的方式
let number = BigInt(Math.pow(2, 53) + 1);
console.log(number);  // 9007199254740992n
console.log(typeof number); // bigint

那么我們看看BigInt處理大型數(shù)字相加處理

let number = BigInt(Math.pow(2, 53));
letnumber2 = BigInt(Math.pow(2, 53));
console.log(number);  // 9007199254740992n
console.log(number2); // 9007199254740992n

letnum = number + number2;
console.log(num);      // 18014398509481984n
console.log(num.toString());  // 18014398509481984

注意:

BigInt 是一種新的數(shù)據(jù)原始(primitive)類型续扔。

5. for-in機(jī)制


ECMAScript遺留了一個(gè)關(guān)于for-in循環(huán)順序的詳細(xì)描述。在 ECMA-262 5rd Edition 中對(duì)遍歷機(jī)制又進(jìn)行了調(diào)整焕数,并未并且規(guī)定具體的規(guī)則纱昧,不同瀏覽器有不同的實(shí)現(xiàn),這導(dǎo)致對(duì)屬性的遍歷順序存在不一致的問(wèn)題堡赔。ES2020 中要求對(duì)象的遍歷實(shí)現(xiàn)上识脆,各瀏覽器要保持一致。

6. 可選鏈(Optional chaining)


以前在處理多層對(duì)象屬性值獲取的時(shí)候,通常需要對(duì)各層級(jí)的屬性進(jìn)行校驗(yàn).

例如

let name = user && user.info && user.info.name

這是一種丑陋但又不得不做的前置校驗(yàn)善已,否則很容易命中 Uncaught TypeError: Cannot read property… 這種錯(cuò)誤灼捂,這極有可能讓你整個(gè)應(yīng)用掛掉。

對(duì)此换团,ES2020 進(jìn)行了優(yōu)化悉稠,可以通過(guò) ?. 來(lái)簡(jiǎn)化校驗(yàn)。

?. 操作符與 . 類似啥寇,兩者的區(qū)別在于偎球,?. 在獲取對(duì)象屬性時(shí)洒扎,如果其引用對(duì)象為 null 或 undefined辑甜,則表達(dá)式會(huì)發(fā)生短路,直接返回 undefined袍冷。

示例代碼如下:

// 1\. 能正確找到屬性值
let user = {
    info:{
        name:"小明"
    }
}
var name = user?.info?.name;
console.log(name);   // 小明

// 2\. 屬性值不存在
let user2 = {
    info:{
        city:"上海"
    }
}
var name2 = user2?.info?.name;
console.log(name2);   // undefined

7. 空值合并運(yùn)算符(Nullish coalescing Operator)


在JavaScript中我們經(jīng)常會(huì)遇到給某個(gè)變量或者對(duì)象的屬性添加默認(rèn)值

示例:

// 三目運(yùn)算符處理默認(rèn)值
const name = user.name ? user.name : "默認(rèn)名稱";

// 邏輯運(yùn)算符中的短路算法處理默認(rèn)值
const name = user.name || "默認(rèn)名稱" 

ES2020 新增了更簡(jiǎn)潔的空值合并操作符(??)磷醋,左側(cè)值為 null 或 undefined 時(shí)返回右側(cè)默認(rèn)值

const name = user.name ?? "默認(rèn)名稱" 

但對(duì)于邏輯或操作符來(lái)說(shuō),''胡诗、0 都會(huì)轉(zhuǎn)化為 false邓线,容易產(chǎn)生邏輯錯(cuò)誤淌友。在業(yè)務(wù)上,大多是是想判斷變量是否為 undefined 或者 null骇陈。

因此要注意,

// user.name的值會(huì)有可能會(huì)進(jìn)行隱式類型轉(zhuǎn)行,為0的時(shí)候,也會(huì)只用默認(rèn)值
const name = user.name || "默認(rèn)名稱" ;

// ES2020新增的?? 運(yùn)算符 有且僅當(dāng)user.name的為null或者undefined時(shí)
// 才會(huì)啟用默認(rèn)值
const name = user.name ?? "默認(rèn)名稱" 

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末震庭,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子你雌,更是在濱河造成了極大的恐慌器联,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件婿崭,死亡現(xiàn)場(chǎng)離奇詭異拨拓,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)氓栈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門渣磷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人授瘦,你說(shuō)我怎么就攤上這事醋界。” “怎么了提完?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵物独,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我氯葬,道長(zhǎng)挡篓,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任帚称,我火速辦了婚禮官研,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘闯睹。我一直安慰自己戏羽,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布楼吃。 她就那樣靜靜地躺著始花,像睡著了一般。 火紅的嫁衣襯著肌膚如雪孩锡。 梳的紋絲不亂的頭發(fā)上酷宵,一...
    開(kāi)封第一講書(shū)人閱讀 51,688評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音躬窜,去河邊找鬼浇垦。 笑死,一個(gè)胖子當(dāng)著我的面吹牛荣挨,可吹牛的內(nèi)容都是我干的男韧。 我是一名探鬼主播朴摊,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼此虑!你這毒婦竟也來(lái)了甚纲?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤朦前,失蹤者是張志新(化名)和其女友劉穎贩疙,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體况既,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡这溅,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了棒仍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片悲靴。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖莫其,靈堂內(nèi)的尸體忽然破棺而出癞尚,到底是詐尸還是另有隱情,我是刑警寧澤乱陡,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布浇揩,位于F島的核電站,受9級(jí)特大地震影響憨颠,放射性物質(zhì)發(fā)生泄漏胳徽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一爽彤、第九天 我趴在偏房一處隱蔽的房頂上張望养盗。 院中可真熱鬧,春花似錦适篙、人聲如沸往核。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)聂儒。三九已至,卻和暖如春硫痰,著一層夾襖步出監(jiān)牢的瞬間衩婚,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工碍论, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留谅猾,地道東北人柄慰。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓鳍悠,卻偏偏與公主長(zhǎng)得像税娜,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子藏研,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容