欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

ES11屢試不爽的新特性,你用上了幾個(gè)

 更新時(shí)間:2020年10月21日 16:15:11   作者:前端Sneaker  
這篇文章主要介紹了ES11屢試不爽的新特性,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

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)文章

最新評(píng)論