ES11屢試不爽的新特性,你用上了幾個(gè)
ES11規(guī)范于今年的年初完成,引入了許多新標(biāo)準(zhǔn),本文講著重研究下其中幾個(gè)實(shí)用且有趣的新標(biāo)準(zhǔn)
特性搶先知:
- 私有變量
- Promise.allSettled
- BigInt 全新的數(shù)據(jù)類(lèi)型
- Nullish Coalescing Operator 空位合并運(yùn)算符
- Optional Chaining Operator 可選鏈運(yùn)算符
- Dynamic Import 動(dòng)態(tài)導(dǎo)入
- String.prototype.matchAll 新增matchAll
- globalThis 新增全局對(duì)象
- Module Namespace Exports 導(dǎo)入特定命名空間
私有變量
嚴(yán)格限制一些用于內(nèi)部使用的Class變量,只需要在變量前 添加# ,就可以使其成為私有變量,并且無(wú)法在class外部直接訪問(wèn)
下面我們以一個(gè)簡(jiǎn)單的
class Hero { #aggressivity = 0 constructor (aggressivity){ this.#aggressivity = aggressivity } getHurt(){ return this.#aggressivity } setAggressivity(aggressivity){ this.#aggressivity = aggressivity } } const shooter = new Hero(100) let hurt = shooter.getHurt() console.log(hurt) //100 console.log(shooter.#aggressivity) //Error : Uncaught SyntaxError: Private field '#aggressivity' must be declared in an enclosing class
上面代碼我們會(huì)發(fā)現(xiàn),無(wú)法直接進(jìn)行訪問(wèn)#aggressivity,將拋出異常
只能通過(guò)class里進(jìn)行訪問(wèn),可通過(guò)統(tǒng)一class的公共方法進(jìn)行統(tǒng)一修改
假設(shè)目前射手?jǐn)y帶了 狂暴 技能,提升了 10%傷害 ,我們可以通過(guò)setAggressivity來(lái)修改攻擊力
let aggressivity = parseInt(hurt * 1.1) shooter.setAggressivity(aggressivity) console.log(shooter.getHurt()) // 110
Promise.allSettled
談及這個(gè)新特性之前,我們先簡(jiǎn)單回顧下 Promise.all 以及 Promise.race ,推測(cè)下為什么需要 Promise.allSettled 這個(gè)新特性
Promise.all:可以將多個(gè)Promise實(shí)例包裝成一個(gè)新的Promise實(shí)例。同時(shí),成功和失敗的返回值是不同的,成功的時(shí)候返回的是一個(gè)結(jié)果數(shù)組,而失敗的時(shí)候則返回最先被reject失敗狀態(tài)的值
let p1 = new Promise((resolve, reject) => { resolve('成功了') }) let p2 = new Promise((resolve, reject) => { resolve('success') }) let p3 = Promse.reject('失敗') Promise.all([p1, p2]).then((result) => { console.log(result) //['成功了', 'success'] }).catch((error) => { console.log(error) }) Promise.all([p1,p3,p2]).then((result) => { console.log(result) }).catch((error) => { console.log(error) // 失敗了,打出 '失敗' })
Promise.race:返回一個(gè)promise,一旦某個(gè)Promise觸發(fā)resolve或者reject,就直接返回該promise結(jié)果狀態(tài)
const promise1 = new Promise((resolve, reject) => { setTimeout(resolve, 500, 'one'); }); const promise2 = new Promise((resolve, reject) => { setTimeout(resolve, 100, 'two'); }); Promise.race([promise1, promise2]).then((value) => { console.log(value); }); //輸出 "two" 因?yàn)閜romise2返回結(jié)果比promise1快
有時(shí)候我們可能需要知道所有的結(jié)果做一些操作,并不關(guān)心其執(zhí)行結(jié)果是否成功,在沒(méi)有Promise.allSettled之前,我們需要自己實(shí)現(xiàn),可通過(guò)如下 實(shí)現(xiàn)Promise.allSettled
let allSettled = (funcArr) => { return new Promise((resolve) => { let sttled = 0 let result = [] for(let index = 0;index<funcArr.length;index++){ const element = funcArr[index] element .then(res => { result[index] = { status: 'fulfilled', value: res } }) .catch(err => { result[index] = { status: 'rejected', reason: err } }) .finally(() => { ++sttled === funcArr.length && resolve(result) }) } }) } //使用 const promises = [ Promise.reject('c'), Promise.resolve('a'), Promise.resolve('b'), ]; allSettled(promises).then(res => { console.log(res) }) // 打印結(jié)果 // [{"status":"rejected","reason":"c"}, // {"status":"fulfilled","value":"a"}, // {"status":"fulfilled","value":"b"}]
而Promise.allSettled新特性出來(lái)后,我們可以直接使用而不需要單獨(dú)去實(shí)現(xiàn)了
const promises = [ Promise.reject('c'), Promise.resolve('a'), Promise.resolve('b'), ]; Promise.allSettled(promises).then(res =>{ console.log(res) }) // 打印結(jié)果 // [{"status":"rejected","reason":"c"}, // {"status":"fulfilled","value":"a"}, // {"status":"fulfilled","value":"b"}]
返回結(jié)果里會(huì)將返回一個(gè)數(shù)組,包含了所有成功與失敗的結(jié)果,數(shù)組每項(xiàng)為對(duì)象,均含有 status 屬性,對(duì)應(yīng)fulfilled和rejected。
當(dāng)狀態(tài)為 fulfilled 時(shí),代表著成功,包含一個(gè) value ,代表著成功的結(jié)果
當(dāng)狀態(tài)為 rejected 時(shí),代表著失敗,包含一個(gè) reason ,代表著失敗的原因
BigInt
JS中缺少顯式整數(shù)類(lèi)型常常令人困惑。許多編程語(yǔ)言支持多種數(shù)字類(lèi)型,如浮點(diǎn)型、雙精度型、整數(shù)型和雙精度型,但JS卻不是這樣。在JS中,按照IEEE 754-2008標(biāo)準(zhǔn)的定義,所有數(shù)字都以雙精度 64位浮點(diǎn)格式 表示。
在此標(biāo)準(zhǔn)下,無(wú)法精確表示的非常大的整數(shù)將自動(dòng)四舍五入。確切地說(shuō),JS 中的Number類(lèi)型只能安全地表示-9007199254740991 (-(2^53-1)) 和9007199254740991(2^53-1)之間的整數(shù),任何超出此范圍的整數(shù)值都可能失去精度。
console.log(9999999999999999); //10000000000000000
JS 提供 Number.MAX_SAFE_INTEGER 常量來(lái)表示 最大安全整數(shù), Number.MIN_SAFE_INTEGER 常量表示最小安全整數(shù):
// 注意最后一位的數(shù)字 const A = Number.MAX_SAFE_INTEGER + 1 const B = Number.MAX_SAFE_INTEGER + 2 console.log(Number.MAX_SAFE_INTEGER) //9007199254740991 console.log(A) //9007199254740992 console.log(B) //9007199254740992 console.log(A === B) //true
當(dāng)數(shù)據(jù)超出范圍就會(huì)失去精度,達(dá)不到我們預(yù)期的結(jié)果。
BigInt橫空出世,可以在標(biāo)準(zhǔn)JS中執(zhí)行對(duì)大整數(shù)的算術(shù)運(yùn)算,不必?fù)?dān)心精度損失風(fēng)險(xiǎn)
創(chuàng)建BigInt數(shù)據(jù)類(lèi)型的方式非常簡(jiǎn)單,在整數(shù)后面追加 n 即可,或者 通過(guò)BigInt()進(jìn)行創(chuàng)建實(shí)例
const bigint = 999999999999999999n const bigintByMethod = BigInt('999999999999999999') console.log(bigint) //999999999999999999n console.log(bigintByMethod) //999999999999999999n console.log(bigint === bigintByMethod) //true //布爾值 console.log(BigInt(true)) //1n console.log(BigInt(false)) //0n console.log(typeof bigint) //"bigint"
BigInt 與 Number是兩種數(shù)據(jù)類(lèi)型,無(wú)法進(jìn)行運(yùn)算,可以進(jìn)行大小比較
console.log(88n == 88) //true console.log(88n === 88) //false console.log(88n+1) //Error =>Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions
BigInt之間, 除了一元加號(hào)(+)運(yùn)算符 外,其他均可用于BigInt
console.log(1n + 2n) //3n console.log(1n - 2n) //-1n console.log(+ 1n) //Uncaught TypeError: Cannot convert a BigInt value to a number console.log(- 1n) //-1n console.log(10n * 20n) //200n console.log(23n%10n) //3n console.log(20n/10n) //2n ......
需要注意的是, 除法運(yùn)算符會(huì)自動(dòng)向下舍入到最接近的整數(shù)
console.log(25n / 10n) //2n console.log(29n / 10n) //2n
最后還有個(gè)注意點(diǎn)就是,Boolean類(lèi)型和BigInt類(lèi)型的轉(zhuǎn)換時(shí),處理方式和Number類(lèi)型,只要 不是0n,BigInt就被視為true
if (5n) { // 這里代碼塊將被執(zhí)行 } if (0n) { // 這里代碼塊不會(huì)執(zhí)行 }
Nullish Coalescing Operator 空位合并運(yùn)算符
新增一個(gè)邏輯運(yùn)算符??,處理null和undefined,工作原理與邏輯or( || )類(lèi)似,但是與此相反
||如果為真即返回左側(cè)值,否則返回右側(cè)
0 || 5 // return 5 "" || 5 // return 5 "前端公蝦米" || 'V5' //return "前端公蝦米"
??如果為null或者undefined,即返回右側(cè),否則返回左側(cè)
0 ?? 5 //return 0 "" ?? 5 //return "" null ?? 5 // return 5 undefined ?? 5 // return 5 false ?? 5 //return false NaN ?? 5 // return NaN
在使用該??運(yùn)算符時(shí),需要注意的是
- 不可與其他運(yùn)算符組合使用,例如&&、||
- 但若使用括號(hào)包裹則可以組合使用
"前端公蝦米" || undefined ?? "Sneaker" //Uncaught SyntaxError: Unexpected token '??' "前端公蝦米" && undefined ?? "Sneaker" //Uncaught SyntaxError: Unexpected token '??' ("前端公蝦米" || undefined) ?? "(๑•̀ㅂ•́)و✧" //"前端公蝦米" ("前端公蝦米" && null) ?? "一起學(xué)習(xí)" //"一起學(xué)習(xí)"
Optional Chaining Operator 可選鏈運(yùn)算符
日常開(kāi)發(fā)中,不少開(kāi)發(fā)者會(huì)碰到Cannot read property XXX of undefined,拋出無(wú)法從未定義的數(shù)據(jù)中讀取某個(gè)字段
可選鏈運(yùn)算符在查找嵌套對(duì)象時(shí),找到鏈中的第一個(gè) undefined 或者 null 后會(huì)立即終止,并返回 undefined ,而不會(huì)不斷向下查找而導(dǎo)致拋錯(cuò)
const obj = { foo: { bar: { baz: 42, }, }, } console.log(obj.fo.bar.baz) //Uncaught TypeError: Cannot read property 'bar' of undefined 在諸如此類(lèi)的對(duì)象里,我們通常進(jìn)行數(shù)據(jù)安全檢查來(lái)訪問(wèn)嵌套對(duì)象,否則將拋錯(cuò) if(obj&&obj.foo&&obj.foo.bar){ console.log(obj.foo.bar.baz) // 42 }
在可選鏈運(yùn)算符可使用的現(xiàn)在,我們只需這樣進(jìn)行屬性的讀取
console.log(obj?.foo?.bar?.baz) //42 console.log(obj.foo.bar?.baz) //42
Dynamic Import 動(dòng)態(tài)導(dǎo)入
在標(biāo)準(zhǔn)的import導(dǎo)入中,是靜態(tài)導(dǎo)入的,所有被導(dǎo)入的模塊是在加載時(shí)就被編譯的,無(wú)法按需編譯。當(dāng)我們需要條件導(dǎo)入的時(shí)候,都只能使用 require() .
但現(xiàn)在,我們有辦法改善此類(lèi)情況了,因?yàn)閯?dòng)態(tài)導(dǎo)入可以有效的減少未使用代碼的編譯,可以提高首屏加載速度,按需加載。
那么,為什么我們需要?jiǎng)討B(tài)導(dǎo)入呢?
- 靜態(tài)導(dǎo)入消耗加載時(shí)間,很多模塊并非首屏需要渲染
- 靜態(tài)導(dǎo)入會(huì)在導(dǎo)入時(shí)消耗大量?jī)?nèi)存
- 可能會(huì)存在有些模塊在加載時(shí)不存在
- 減少一些有條件依賴(lài)的副作用
//通用導(dǎo)入方式 import("/module/sneaker/test.js") .then(module => { //模塊相關(guān)操作 }) //await const getModule = await import("/module/sneaker/test.js") //通過(guò)async await const getUserInfo = async (hasLogin) => { if(!hasLogin){ const user = await import("/module/sneaker/user.js") user.getInfo() } }
matchAll
基于String原型上的一個(gè)新方法,允許我們匹配一個(gè)字符串和一個(gè)正則表達(dá)式,返回值是所有匹配結(jié)果的迭代器。
可以通過(guò) for...of 遍歷或者 操作符... 、 Array.from 將結(jié)果迭代器轉(zhuǎn)換成數(shù)組
const string = 'Hello Sneaker,Where is the library?' const regex = /[A-W]/g const matches = string.matchAll(regex) console.log(...matches) //["H", index: 0, input: "Hello Sneaker,Where is the library?", groups: undefined] //["S", index: 6, input: "Hello Sneaker,Where is the library?", groups: undefined] //["W", index: 14, input: "Hello Sneaker,Where is the library?", groups: undefined]
globalThis
這是為了提供一種訪問(wèn)全局對(duì)象的標(biāo)準(zhǔn)方法。
在瀏覽器中,我們可以使用 window/self/frames 來(lái)訪問(wèn)全局對(duì)象,但對(duì)于Web Workers只能使用 self ,Node中又完全不同,需要使用 global 。
在 globalThis 成為標(biāo)準(zhǔn)之前,獲取全局對(duì)象我們可能需要這么做
const globalObj = (()=>{ if(self) return self if(window) return window if(global) return global throw new Error('Sorry!No global obj found') })
//Browser globalThis === window //true //Webworker globalThis === self //true //Node globalThis === global //true
從此實(shí)現(xiàn)全局對(duì)象的大一統(tǒng)!
Module Namespace Exports 導(dǎo)入特定命名空間
export * as ns from './module //等同于 import * as ns from './module' export {ns}
導(dǎo)入特定命名空間實(shí)則并沒(méi)有導(dǎo)入模塊,只是對(duì)模塊進(jìn)行轉(zhuǎn)發(fā),導(dǎo)致在此模塊中不可直接使用此模塊
參考
- ecma-262
- MDN
最后
特性很多但有的很有趣,比如可選鏈和空位合并運(yùn)算符,屢試不爽,至于有多爽,你試了才知道。新特性平常不寫(xiě)還是容易忽略淡忘的,建議平??梢韵乱庾R(shí)的經(jīng)常回顧運(yùn)用,一起學(xué)習(xí)一起成長(zhǎng)。
到此這篇關(guān)于ES11屢試不爽的新特性,你用上了幾個(gè)的文章就介紹到這了,更多相關(guān)ES11 新特性?xún)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解webpack+express多頁(yè)站點(diǎn)開(kāi)發(fā)
這篇文章主要介紹了詳解webpack+express多頁(yè)站點(diǎn)開(kāi)發(fā)2017-12-12解決input輸入框僅支持輸入數(shù)字及兩位小數(shù)點(diǎn)的限制
這篇文章主要為大家介紹了解決input輸入框僅支持輸入數(shù)字及兩位小數(shù)點(diǎn)的限制技巧示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11javascript實(shí)現(xiàn)點(diǎn)擊按鈕切換輪播圖功能
這篇文章主要為大家詳細(xì)介紹了javascript實(shí)現(xiàn)點(diǎn)擊按鈕切換輪播圖功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-09-09webpack 如何解析代碼模塊路徑的實(shí)現(xiàn)
這篇文章主要介紹了webpack 如何解析代碼模塊路徑的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09php對(duì)mongodb的擴(kuò)展(小試牛刀)
本文主要講解php連接、操作mongodb,有需求的朋友可以參考下2012-11-112022發(fā)布ECMAScript新特性盤(pán)點(diǎn)
這篇文章主要為大家介紹了2022發(fā)布ECMAScript新特性盤(pán)點(diǎn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07JavaScript實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)的幾種常用方式
這篇文章主要介紹了JavaScript實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)的幾種常用方式,結(jié)合實(shí)例形式對(duì)比分析了JavaScript頁(yè)面跳轉(zhuǎn)的常見(jiàn)實(shí)現(xiàn)技巧與相關(guān)注意事項(xiàng),具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11JS實(shí)現(xiàn)Excel導(dǎo)出功能以及導(dǎo)出亂碼問(wèn)題解決詳解
這篇文章主要為大家詳細(xì)介紹了JavaScript如何調(diào)用后臺(tái)接口實(shí)現(xiàn)Excel導(dǎo)出功能以及導(dǎo)出亂碼問(wèn)題的解決辦法,需要的小伙伴可以參考一下2023-07-07