溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

ES6實(shí)用方法有哪些

發(fā)布時(shí)間:2021-10-23 16:44:15 來(lái)源:億速云 閱讀:128 作者:iii 欄目:web開(kāi)發(fā)

這篇文章主要講解了“ES6實(shí)用方法有哪些”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“ES6實(shí)用方法有哪些”吧!

 
ES6實(shí)用方法有哪些

Array.prototype.includes

判斷一個(gè)數(shù)組是否包含某個(gè)元素,之前一般是這么做的:

if (arr.indexOf(el) >= 0) {}  // 或者 if (~arr.indexOf(el)) {}

而現(xiàn)在你可以這么做了:

if (arr.includes(el)) {}

indexOf 會(huì)返回找到元素在數(shù)組中的索引位置,判斷的邏輯是是否嚴(yán)格相等,所以他在遇到 NaN 的時(shí)候不能正確返回索引,但是 includes  解決了這個(gè)問(wèn)題:

[1, NaN, 3].indexOf(NaN)   // -1 [1, NaN, 3].includes(NaN)  // true

求冪運(yùn)算符(**)

x ** y 是求 x 的 y 次冪,和 Math.pow(x, y) 功能一致:

// x ** y let squared = 2 ** 2  // 2 * 2 = 4 let cubed = 2 ** 3    // 2 * 2 * 2 = 8

x **= y 表示求 x 的 y 次冪,并且把結(jié)果賦值給 x:

// x **= y let x = 2; x **= 3  // x 最后等于 8

ES2017

ES6實(shí)用方法有哪些

Object.values()

返回一個(gè)由對(duì)象自身所有可遍歷屬性的屬性值組成的數(shù)組:

const person = { name: '布蘭' }; Object.defineProperty(person, 'age', {     value: 12,     enumrable: false  // age 屬性將不可遍歷 }) console.log(Object.values(person))  // ['布蘭']  // 類似 str.split('') 效果 console.log(Object.values('abc'))  // ['a', 'b', 'c']

Object.entries()

返回一個(gè)由對(duì)象自身所有可遍歷屬性的鍵值對(duì)組成的數(shù)組:

const person = { name: '布蘭', age: 12 } console.log(Object.entries(person))  // [["name", "布蘭"], ["age", 12]]

利用這個(gè)方法可以很好的將對(duì)象轉(zhuǎn)成正在的 Map 結(jié)構(gòu):

const person = { name: '布蘭', age: 12 } const map = new Map(Object.entries(person)) console.log(map)  // Map { name: '布蘭', age: 12 }

Object.getOwnPropertyDescriptors()

Object.getOwnPropertyDescriptor() 會(huì)返回指定對(duì)象某個(gè)自身屬性的的描述對(duì)象,而  Object.getOwnPropertyDescriptors() 則是返回指定對(duì)象自身所有屬性的描述對(duì)象:

const person = { name: '布蘭', age: 12 }  console.log(Object.getOwnPropertyDescriptor(person, 'name')) // { configurable: true, enumerable: true, value: "布蘭", writable: true }  console.log(Object.getOwnPropertyDescriptors(person)) //{  //  name: { configurable: true, enumerable: true, value: "布蘭", writable: true }, //  age: {configurable: false, enumerable: false, value: 12, writable: false} //}

配合 Object.create() 可以實(shí)現(xiàn)淺克?。?/p>

const shallowClone = (obj) => Object.create(     Object.getPrototypeOf(obj),     Object.getOwnPropertyDescriptors(obj) )

String.prototype.padStart()

str.padStart(length [, padStr]) 會(huì)返回一個(gè)新字符串,該字符串將從 str 字符串的左側(cè)開(kāi)始填充某個(gè)字符串  padStr(非必填,如果不是字符串則會(huì)轉(zhuǎn)成字符串, 傳入 undefined 和不傳這個(gè)參數(shù)效果一致)直到達(dá)到指定位數(shù) length 為止:

'abc'.padStart(5, 2)          // '22abc' 'abc'.padStart(5, undefined)  // '  abc' 'abc'.padStart(5, {})         // '[oabc' 'abc'.padStart(5)             // '  abc' 'abcde'.padStart(2, 'f')      // 'abcde'

String.prototype.padEnd()

規(guī)則和 padStart 類似,但是是從字符串右側(cè)開(kāi)始填充:

'abc'.padEnd(5, 2)  // 'abc22'

函數(shù)參數(shù)尾逗號(hào)

允許函數(shù)在定義和調(diào)用的時(shí)候時(shí)候最后一個(gè)參數(shù)后加上逗號(hào):

function init(     param1,      param2,   ) { }  init('a', 'b',)

Async函數(shù)

使用 async 可以聲明一個(gè) async 函數(shù),結(jié)合 await 可以用一種很簡(jiǎn)介的方法寫成基于 Promise  的異步行為,而不需要刻意的鏈?zhǔn)秸{(diào)用。await 表達(dá)式會(huì)暫停整個(gè) async 函數(shù)的執(zhí)行進(jìn)程并出讓其控制權(quán),只有當(dāng)其等待的基于 Promise  的異步操作被兌現(xiàn)或被拒絕之后才會(huì)恢復(fù)進(jìn)程。async 函數(shù)有如下幾種定義形式:

// 函數(shù)聲明 async function foo() {}  // 函數(shù)表達(dá)式 let foo = async function() {}  // 箭頭函數(shù) let foo = async () => {}  // 對(duì)象方法 lef obj = {     async foo() {} }  // 類方法 class Dog {     async bark() {} }

async 函數(shù)一定會(huì)返回一個(gè) Promise 對(duì)象,所以它可以使用 then 添加處理函數(shù)。如果一個(gè) async  函數(shù)的返回值看起來(lái)不是Promise,那么它將會(huì)被隱式地包裝在一個(gè) Promise 中:

async function foo() {     return 'a' } foo().then(res => {     console.log(res)  // 'a' })

內(nèi)部如果發(fā)生錯(cuò)誤,或者顯示拋出錯(cuò)誤,那么 async 函數(shù)會(huì)返回一個(gè) rejected 狀態(tài)的 Promsie:

async function foo() {     throw new Error('error') } foo().catch(err => {     console.log(err)  // Error: error })

返回的 Promise 對(duì)象必須等到內(nèi)部所有 await 命令 Promise 對(duì)象執(zhí)行完才會(huì)發(fā)生狀態(tài)改變,除非遇到 return  語(yǔ)句或拋出錯(cuò)誤;任何一個(gè) await 命令返回的 Promise 對(duì)象變 為rejected 狀態(tài),整個(gè) Async 函數(shù)都會(huì)中斷后續(xù)執(zhí)行:

async function fn() {     let a = await Promise.resolve('success')     console.log('a_' + a)     let b = await Promise.reject('fail')     console.log('b_' + b)  // 不會(huì)執(zhí)行 } fn().then(res => {     console.log(res)  // 不會(huì)執(zhí)行 }, err => {     console.log(err) }) // 'a_success' // 'fail'

所以為了保證 async 里的異步操作都能完成,我們需要將他們放到 try...catch() 塊里或者在 await 返回的 Promise 后跟一個(gè)  catch 處理函數(shù):

async function fn() {     try {         let a = await Promise.reject('a fail')         console.log('a_' + a)  // 不會(huì)執(zhí)行     } catch (e) {         console.log(e)  // 'a fail'     }     let b = await Promise.reject('b fail')         .catch(e => {             console.log(e)  // 'b fail'         })     console.log('b_' + b)  // 'bundefined' } fn().then(res => {     console.log(res)  // undefined }, err => {     console.log(err)  // 不會(huì)執(zhí)行 })

如果 async 函數(shù)里的多個(gè)異步操作之間沒(méi)有依賴關(guān)系,建議將他們寫到一起減少執(zhí)行時(shí)間:

// 寫法一 let [foo, bar] = await Promise.all([getFoo(), getBar()])  // 寫法二 let fooPromise = getFoo() let barPromise = getBar() let foo = await fooPromise let bar = await barPromise

await 命令只能用在 async 函數(shù)之中,如果用在普通函數(shù),就會(huì)報(bào)錯(cuò)。

共享內(nèi)存和Atomics對(duì)象

  • SharedArrayBuffer

  • Atomics

ES2018

ES6實(shí)用方法有哪些

Promise.prototype.finally()

Promise.prototype.finally() 用于給 Promise 對(duì)象添加 onFinally  函數(shù),這個(gè)函數(shù)主要是做一些清理的工作,只有狀態(tài)變化的時(shí)候才會(huì)執(zhí)行該 onFinally 函數(shù)。

function onFinally() {     console.log(888)  // 并不會(huì)執(zhí)行   } new Promise((resolve, reject) => {      }).finally(onFinally)

finally() 會(huì)生成一個(gè) Promise 新實(shí)例,finally 一般會(huì)原樣后傳父 Promise,無(wú)論父級(jí)實(shí)例是什么狀態(tài):

let p1 = new Promise(() => {}) let p2 = p1.finally(() => {}) setTimeout(console.log, 0, p2)  // Promise {<pending>}  let p3 = new Promise((resolve, reject) => {     resolve(3) }) let p4 = p3.finally(() => {}) setTimeout(console.log, 0, p3)  // Promise {<fulfilled>: 3}

上面說(shuō)的是一般,但是也有特殊情況,比如 finally 里返回了一個(gè)非 fulfilled 的 Promise  或者拋出了異常的時(shí)候,則會(huì)返回對(duì)應(yīng)狀態(tài)的新實(shí)例:

let p1 = new Promise((resolve, reject) => {     resolve(3) }) let p2 = p1.finally(() => new Promise(() => {})) setTimeout(console.log, 0, p2)  // Promise {<pending>}  let p3 = p1.finally(() => Promise.reject(6)) setTimeout(console.log, 0, p3)  // Promise {<rejected>: 6}  let p4 = p1.finally(() => {     throw new Error('error') }) setTimeout(console.log, 0, p4)  // Promise {<rejected>: Error: error}

參考:

  • 深入理解Promise

異步迭代器

想要了解異步迭代器最好的方式就是和同步迭代器進(jìn)行對(duì)比。我們知道可迭代數(shù)據(jù)的內(nèi)部都是有一個(gè) Symbol.iterator  屬性,它是一個(gè)函數(shù),執(zhí)行后會(huì)返回一個(gè)迭代器對(duì)象,這個(gè)迭代器對(duì)象有一個(gè) next() 方法可以對(duì)數(shù)據(jù)進(jìn)行迭代,next() 執(zhí)行后會(huì)返回一個(gè)對(duì)象,包含了當(dāng)前迭代值  value 和 標(biāo)識(shí)是否完成迭代的 done 屬性:

let iterator = [1, 2][Symbol.iterator]() iterator.next()  // { value: 1, done: false } iterator.next()  // { value: 2, done: false } iterator.next()  // { value: undefinde, done: true }

上面這里的 next() 執(zhí)行的是同步操作,所以這個(gè)是同步迭代器,但是如果 next()  里需要執(zhí)行異步操作,那就需要異步迭代了,可異步迭代數(shù)據(jù)的內(nèi)部有一個(gè) Symbol.asyncIterator屬性,基于此我們來(lái)實(shí)現(xiàn)一個(gè)異步迭代器:

class Emitter {     constructor(iterable) {         this.data = iterable     }     [Symbol.asyncIterator]() {         let length = this.data.length,             index = 0;                  return {             next:() => {                 const done = index >= length                 const value = !done ? this.data[index++] : undefined                 return new Promise((resolve, reject) => {                     resolve({value, done})                 })             }         }     } }

異步迭代器的 next() 會(huì)進(jìn)行異步的操作,通常是返回一個(gè) Promise,所以需要對(duì)應(yīng)的處理函數(shù)去處理結(jié)果:

let emitter = new Emitter([1, 2, 3]) let asyncIterator = emitter[Symbol.asyncIterator]() asyncIterator.next().then(res => {     console.log(res)  // { value: 1, done: false } }) asyncIterator.next().then(res => {     console.log(res)  // { value: 2, done: false } }) asyncIterator.next().then(res => {     console.log(res)  // { value: 3, done: false } })

另外也可以使用 for await...of 來(lái)迭代異步可迭代數(shù)據(jù):

let asyncIterable = new Emitter([1, 2, 3]) async function asyncCount() {     for await (const x of asyncIterable ) {         console.log(x)     } } asyncCount() // 1 2 3

另外還可以通過(guò)異步生成器來(lái)創(chuàng)建異步迭代器:

class Emitter {     constructor(iterable) {         this.data = iterable     }     async *[Symbol.asyncIterator]() {         let length = this.data.length,             index = 0;                      while (index < length) {             yield this.data[index++]         }     } } async function asyncCount() {     let emitter = new Emitter([1, 2, 3])     const asyncIterable = emitter[Symbol.asyncIterator]()     for await (const x of asyncIterable ) {         console.log(x)     } } asyncCount() // 1 2 3

參考:

  • Iteration_protocols

  • for-await...of

s修飾符(dotAll模式)

正則表達(dá)式新增了一個(gè) s 修飾符,使得 . 可以匹配任意單個(gè)字符:

/foo.bar/.test('foo\nbar')   // false /foo.bar/s.test('foo\nbar')  // true

上面這又被稱為 dotAll  模式,表示點(diǎn)(dot)代表一切字符。所以,正則表達(dá)式還引入了一個(gè)dotAll屬性,返回一個(gè)布爾值,表示該正則表達(dá)式是否處在dotAll模式:

/foo.bar/s.dotAll  // true

具名組匹配

正則表達(dá)式可以使用捕獲組來(lái)匹配字符串,但是想要獲取某個(gè)組的結(jié)果只能通過(guò)對(duì)應(yīng)的索引來(lái)獲?。?/p>

let re = /(\d{4})-(\d{2})-(\d{2})/ let result = re.exec('2015-01-02') // result[0] === '2015-01-02' // result[1] === '2015' // result[2] === '01' // result[3] === '02'

而現(xiàn)在我們可以通過(guò)給捕獲組 (?...) 加上名字 name ,通過(guò)名字來(lái)獲取對(duì)應(yīng)組的結(jié)果:

let re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/ let result = re.exec('2015-01-02') // result.groups.year === '2015' // result.groups.month === '01' // result.groups.day === '02'

配合解構(gòu)賦值可以寫出非常精簡(jiǎn)的代碼:

let {groups: {year, month, day}} = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/.exec('2015-01-02') console.log(year, month, day)  // 2015 01 02

具名組也可以通過(guò)傳遞給 String.prototype.replace 的替換值中進(jìn)行引用。如果該值為字符串,則可以使用 $獲取到對(duì)應(yīng)組的結(jié)果:

let re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/ let result = '2015-01-02'.replace(re, '$<day>/$<month>/$<year>') // result === '02/01/2015'

參考:

  • proposal-regexp-named-groups

后行斷言

后行斷言: (?<=y)x,x 只有在 y 后面才能匹配:

/(?<=\$)\d+/.exec('I have $100.')  // ['100']

后行否定斷言: (?<=y)x,x 只有在 y 后面才能匹配:

/(?<!\$)\d+/.exec('I have $100.')  // ['00']

Unicode屬性轉(zhuǎn)義

允許正則表達(dá)式匹配符合 Unicode 某種屬性的所有字符,\p{...} 是匹配包含,\P{...}是匹配不包含的字符,且必須搭配 /u  修飾符才會(huì)生效:

/\p{Emoji}+/u.exec('??笑死我了??不行了')  // ['??'] /\P{Emoji}+/u.exec('??笑死我了??不行了')  // ['笑死我了']

這里可以查詢到更多的 Unicode 的屬性 Full_Properties

對(duì)象擴(kuò)展運(yùn)算符

對(duì)象的擴(kuò)展運(yùn)算符可以用到解構(gòu)賦值上,且只能應(yīng)用到最后一個(gè)變量上:

let {x, ...y} = {x: 1, a: 2, b: 3} console.log(y)  // {a: 2, b: 3}

對(duì)象擴(kuò)展運(yùn)算符不能解構(gòu)原型上的屬性:

let obj = { x: 1 } obj.__proto__ = { y: 2 } let {...a} = obj console.log(a.y)  // undefined

應(yīng)用一:可以實(shí)現(xiàn)淺拷貝,但是不會(huì)拷貝原始屬性:

let person = Object.create({ name: '布蘭' }) person.age = 12  // 淺拷貝寫法一 let { ...pClone1 } = person console.log(pClone1)  // { age: 12 } console.log(pClone1.name)  // undefined  // 淺拷貝寫法二 let pClone2 = {...person} console.log(pClone2)  // { age: 12 } console.log(pClone2.name)  // undefined

應(yīng)用二:合并兩個(gè)對(duì)象:

let ab = {...a, ...b}  // 等同于 let ab = Object.assign({}, a, b);

應(yīng)用三:重寫對(duì)象屬性

let aWithOverrides = { ...a, x: 1, y: 2 };

應(yīng)用四:給新對(duì)象設(shè)置默認(rèn)值

let aWithDefaults = { x: 1, y: 2, ...a };

應(yīng)用五:利用擴(kuò)展運(yùn)算符的解構(gòu)賦值可以擴(kuò)展函數(shù)參數(shù):

function baseFunction({ a, b }) {} function wrapperFunction({ x, y, ...restConfig }) {     // 使用 x 和 y 參數(shù)進(jìn)行操作     // 其余參數(shù)傳給原始函數(shù)     return baseFunction(restConfig) }

參考:

  • Object Spread Initializer

  • Object Rest Destructuring

放松對(duì)標(biāo)簽?zāi)0謇镒址D(zhuǎn)義的限制

參考:

  • ECMAScript 6 入門

ES2019

ES6實(shí)用方法有哪些

允許省略catch里的參數(shù)

異常被捕獲的時(shí)候如果不需要做操作,甚至可以省略 catch(err) 里的參數(shù)和圓括號(hào):

try {  } catch {      }

JSON.stringify()變動(dòng)

UTF-8 標(biāo)準(zhǔn)規(guī)定,0xD800 到 0xDFFF 之間的碼點(diǎn),不能單獨(dú)使用,必須配對(duì)使用。 所以 JSON.stringify()  對(duì)單個(gè)碼點(diǎn)進(jìn)行操作,如果碼點(diǎn)符合 UTF-8 標(biāo)準(zhǔn),則會(huì)返回對(duì)應(yīng)的字符,否則會(huì)返回對(duì)應(yīng)的碼點(diǎn):

JSON.stringify('\u{1f600}')  // ""?"" JSON.stringify('\u{D834}')  // ""\ud834""

Symbol.prototype.description

Symbol 實(shí)例新增了一個(gè)描述屬性 description:

let symbol = Symbol('foo') symbol.description  // 'foo'

Function.prototype.toString()

函數(shù)的 toString() 會(huì)原樣輸出函數(shù)定義時(shí)候的樣子,不會(huì)省略注釋和空格。

Object.fromEntries()

Object.fromEntries() 方法是 Object.entries() 的逆操作,用于將一個(gè)鍵值對(duì)數(shù)組轉(zhuǎn)為對(duì)象:

let person = { name: '布蘭', age: 12 } let keyValueArr = Object.entries(person)   // [['name', '布蘭'], ['age', 12]] let obj = Object.fromEntries(arr)  // { name: '布蘭', age: 12 }

常用可迭代數(shù)據(jù)結(jié)構(gòu)之間的裝換:

let person = { name: '布蘭', age: 12 }  // 對(duì)象 -> 鍵值對(duì)數(shù)組 let keyValueArr = Object.entries(person)  // [['name', '布蘭'], ['age', 12]]  // 鍵值對(duì)數(shù)組 -> Map let map = new Map(keyValueArr)  // Map {"name": "布蘭", "age": 12}  // Map -> 鍵值對(duì)數(shù)組 let arr = Array.from(map)  // [['name', '布蘭'], ['age', 12]]   // 鍵值對(duì)數(shù)組 -> 對(duì)象 let obj = Array.from(arr).reduce((acc, [ key, val ]) => Object.assign(acc, { [key]: val }), {})  // { name: '布蘭', age: 12 }

參考:

  • Object.fromEntries

字符串可直接輸入行分隔符和段分隔符

JavaScript 規(guī)定有 5 個(gè)字符,不能在字符串里面直接使用,只能使用轉(zhuǎn)義形式。

  • U+005C:反斜杠(reverse solidus)

  • U+000D:回車(carriage return)

  • U+2028:行分隔符(line separator)

  • U+2029:段分隔符(paragraph separator)

  • U+000A:換行符(line feed)

但是由于 JSON 允許字符串里可以使用 U+2028 和 U+2029,所以使得 JSON.parse() 去解析字符串的時(shí)候可能會(huì)報(bào)錯(cuò),所以  ES2019 允許模板字符串里可以直接這兩個(gè)字符:

JSON.parse('"\u2028"')  // "" JSON.parse('"\u2029"')  // "" JSON.parse('"\u005C"')  // SyntaxError

String.prototype.trimStart

消除字符串頭部空格,返回一個(gè)新字符串;瀏覽器還額外增加了它的別名函數(shù) trimLeft():

let str = '  hello world ' let newStr = str.trimStart() console.log(newStr, newStr === str)  // 'hello world '  false

String.prototype.trimEnd

消除字符串尾部空格,返回一個(gè)新字符串;瀏覽器還額外增加了它的別名函數(shù) trimRight():

let str = '  hello world ' let newStr = str.trimEnd() console.log(newStr, newStr === str)  // '  hello world'  false

Array.prototype.flat()

arr.flat(depth) 按照 depth (不傳值的話默認(rèn)是 1)深度拍平一個(gè)數(shù)組,并且將結(jié)果以新數(shù)組形式返回:

// depth 默認(rèn)是 1 const arr1 = [1, 2, [3, 4]] console.log(arr1.flat())  // [1, 2, 3, 4]  // 使用 Infinity,可展開(kāi)任意深度的嵌套數(shù)組;自動(dòng)跳過(guò)空數(shù)組; const arr2 = [1, , [2, [3, [4]]]] console.log(arr2.flat(Infinity)) // [1, 2, 3, 4]

用 reduce 實(shí)現(xiàn)拍平一層數(shù)組:

const arr = [1, 2, [3, 4]]  // 方法一 let newStr = arr.reduce((acc, cur) => acc.concat(cur), [])  // 方法二 const flattened = arr => [].concat(...arr) flattened(arr)

參考:

  • flat

Array.prototype.flatMap()

flatMap(callback) 使用映射函數(shù) callback 映射每個(gè)元素,callback 每次的返回值組成一個(gè)數(shù)組,并且將這個(gè)數(shù)組執(zhí)行類似  arr.flat(1) 的操作進(jìn)行拍平一層后最后返回結(jié)果:

const arr1 = [1, 2, 3, 4]  arr1.flatMap(x => [x * 2]) // 將 [[2], [4], [6], [8]] 數(shù)組拍平一層得到最終結(jié)果:[2, 4, 6, 8]

參考:

  • flatMap

ES2020

ES6實(shí)用方法有哪些

String.prototype.matchAll()

String.prototype.matchAll() 方法,可以一次性取出所有匹配。不過(guò),它返回的是一個(gè) RegExpStringIterator  迭代器同是也是一個(gè)可迭代的數(shù)據(jù)結(jié)構(gòu),所以可以通過(guò) for...of 進(jìn)行迭代:

let str = 'test1test2' let regexp = /t(e)(st(\d?))/g let iterable = str.matchAll(regexp) for (const x of iterable) {     console.log(x) } // ['test1', 'e', 'st1', '1', index: 0, input: 'test1test1', groups: undefined] // ['test2', 'e', 'st2', '2', index: 5, input: 'test1test2', groups: undefined]

?注意當(dāng)使用 matchAll(regexp) 的時(shí)候,正則表達(dá)式必須加上 /g 修飾符。?

也可以將這個(gè)可迭代數(shù)據(jù)轉(zhuǎn)成數(shù)組形式:

// 方法一 [...str.matchAll(regexp)]  // 方法二 Array.from(str.matchAll(regexp))

動(dòng)態(tài)import()

標(biāo)準(zhǔn)用法的 import  導(dǎo)入的模塊是靜態(tài)的,會(huì)使所有被導(dǎo)入的模塊,在加載時(shí)就被編譯(無(wú)法做到按需編譯,降低首頁(yè)加載速度)。有些場(chǎng)景中,你可能希望根據(jù)條件導(dǎo)入模塊或者按需導(dǎo)入模塊,這時(shí)你可以使用動(dòng)態(tài)導(dǎo)入代替靜態(tài)導(dǎo)入。

比如按需加載一個(gè)模塊可以這樣:

if (xxx) {     import('./module.js') }

import() 是異步導(dǎo)入的,結(jié)果會(huì)返回一個(gè) Promise:

import('/module.js') .then((module) => {     // Do something with the module. })

動(dòng)態(tài) import() 的應(yīng)用場(chǎng)景挺多的,比如 Vue 中的路由懶加載就是使用的動(dòng)態(tài)導(dǎo)入組件。另外由于動(dòng)態(tài)性不便于靜態(tài)分析工具和 tree-shaking  工作,所以不能濫用。

BigInt

BigInt 是一種內(nèi)置對(duì)象,它提供了一種方法來(lái)表示大于 - 1 的整數(shù)。這原本是 Javascript 中可以用 Number  表示的最大數(shù)字。BigInt 可以表示任意大的整數(shù)。

為了區(qū)分 Number,定義一個(gè) BigInt 需要在整數(shù)后面加上一個(gè) n,或者用函數(shù)直接定義:

const num1 = 10n const num2 = BigInt(20)

Number 和 BigInt 之間能進(jìn)行比較,但他們之間是寬松相等;且由于他們表示的是不同類型的數(shù)字,所以不能直接進(jìn)行四則運(yùn)算:

10n == 10         // true 10n === 10        // false 10n > 8           // true 10 + Number(10n)  // 20 10 + 10n          // TypeError

Promise.allSettled

Promise.allSettled(iterable) 當(dāng)所有的實(shí)例都已經(jīng)  settled,即狀態(tài)變化過(guò)了,那么將返回一個(gè)新實(shí)例,該新實(shí)例的內(nèi)部值是由所有實(shí)例的值和狀態(tài)組合成的數(shù)組,數(shù)組的每項(xiàng)是由每個(gè)實(shí)例的狀態(tài)和內(nèi)部值組成的對(duì)象。

function init(){     return 3 } let p1 = Promise.allSettled([     new Promise((resolve, reject) => {         resolve(9)     }).then(res => {}),     new Promise((resolve, reject) => {         reject(6)     }),     init() ]) let p2 = p1.then(res => {     console.log(res) }, err => {     console.log(err) }) // [ //      {status: "fulfilled", value: undefined},  //      {status: "rejected", reason: 6},  //      {status: "fulfilled", value: 3} // ]

只要所有實(shí)例中包含一個(gè) pending 狀態(tài)的實(shí)例,那么 Promise.allSettled() 的結(jié)果為返回一個(gè)這樣 Promise  {} 的實(shí)例。

globalThis

在以前,從不同的 JavaScript 環(huán)境中獲取全局對(duì)象需要不同的語(yǔ)句。在 Web 中,可以通過(guò) window、self 或者 frames  取到全局對(duì)象,但是在 Web Workers 中,只有 self 可以。在 Node.js 中,它們都無(wú)法獲取,必須使用 global。

而現(xiàn)在只需要使用 globalThis 即可獲取到頂層對(duì)象,而不用擔(dān)心環(huán)境問(wèn)題。

// 在瀏覽器中 globalThis === window  // true

import.meta

import.meta 是一個(gè)給 JavaScript 模塊暴露特定上下文的元數(shù)據(jù)屬性的對(duì)象。它包含了這個(gè)模塊的信息,比如說(shuō)這個(gè)模塊的  URL,import.meta 必須在一個(gè)模塊里使用:

// 沒(méi)有聲明 type="module",就使用 import.meta 會(huì)報(bào)錯(cuò) <script type="module" src="./js/module.js"></script>  // 在module.js里 console.log(import.meta)   // {url: "http://localhost/3ag/js/module.js"}

如果需要在配置了 Webpack 的項(xiàng)目,比如 Vue 里使用 import.meta 需要加一個(gè)包且配置一下參數(shù),否則項(xiàng)目編譯階段會(huì)報(bào)錯(cuò)。

包配置詳情參考:

  • @open-wc/webpack-import-meta-loader

比如我用的是 4.x 版本的 vue-cli,那我需要在 vue.config.js 里配置:

module.exports = {     chainWebpack: config => {         config.module             .rule('js')             .test(/\.js$/)             .use('@open-wc/webpack-import-meta-loader')                 .loader('@open-wc/webpack-import-meta-loader')                 .end()     } }

可選鏈操作符(?.)

通常我們獲取一個(gè)深層對(duì)象的屬性會(huì)需要寫很多判斷或者使用邏輯與 && 操作符,因?yàn)閷?duì)象的某個(gè)屬性如果為 null 或者 undefined  就有可能報(bào)錯(cuò):

let obj = {     first: {         second: '布蘭'     } }  // 寫法一 let name1 = '' if (obj) {     if (obj.first) {         name1 = obj.first.second     } }  // 寫法二 let name2 = obj && obj.first && obj.first.second

?. 操作符允許讀取位于連接對(duì)象鏈深處的屬性的值,而不必明確驗(yàn)證鏈中的每個(gè)引用是否有效。如果某個(gè)屬性為 null 或者 undefined 則結(jié)果直接為  undefined。有了可選鏈操作符就可以使得表達(dá)式更加簡(jiǎn)明了,對(duì)于上面例子用可選鏈操作符可以這么寫:

let name3 = obj?.first?.second

空值合并操作符(??)

對(duì)于邏輯或 || 運(yùn)算符,當(dāng)對(duì)運(yùn)算符左側(cè)的操作數(shù)進(jìn)行裝換為 Boolean 值的時(shí)候,如果為  true,則取左邊的操作數(shù)為結(jié)果,否則取右邊的操作數(shù)為結(jié)果:

let name = '' || '布蘭' console.log(name)  // '布蘭'

我們都知道 ''、0、null、undefined、false、NaN 等轉(zhuǎn)成 Boolean 值的時(shí)候都是  false,所以都會(huì)取右邊的操作數(shù)。這個(gè)時(shí)候如果要給變量設(shè)置默認(rèn)值,如果遇到本身值就可能是 '' 或 0 的情況那就會(huì)出錯(cuò)了,會(huì)被錯(cuò)誤的設(shè)置為默認(rèn)值了。

而 ?? 操作符就是為了解決這個(gè)問(wèn)題而出現(xiàn)的,x ?? y 只有左側(cè)的操作數(shù)為 null 或 undefined  的時(shí)候才取右側(cè)操作數(shù),否則取左側(cè)操作數(shù):

let num = 0 ?? 1 console.log(num)  // 0

ES2021

ES6實(shí)用方法有哪些

如下這幾個(gè)提案已經(jīng)確定了會(huì)在 2021 年發(fā)布,所以把他們歸到 ES2021 中。

String.prototype.replaceAll

之前需要替換一個(gè)字符串里的全部匹配字符可以這樣做:

const queryString = 'q=query+string+parameters'  // 方法一 const withSpaces1 = queryString.replace(/\+/g, ' ')  // 方法二 const withSpaces2 = queryString.split('+').join(' ')

而現(xiàn)在只需要這么做:

const withSpace3 = queryString.replaceAll('+', ' ')

?replaceAll 的第一個(gè)參數(shù)可以是字符串也可以是正則表達(dá)式,當(dāng)是正則表達(dá)式的時(shí)候,必須加上全局修飾符 /g,否則報(bào)錯(cuò)。?

參考:

  • string-replaceall

Promise.any()

Promsie.any() 和 Promise.all() 一樣接受一個(gè)可迭代的對(duì)象,然后依據(jù)不同的入?yún)?huì)返回不同的新實(shí)例:

傳一個(gè)空的可迭代對(duì)象或者可迭代對(duì)象所有 Promise 都是 rejected 狀態(tài)的,則會(huì)拋出一個(gè) AggregateError  類型的錯(cuò)誤,同時(shí)返回一個(gè) rejected 狀態(tài)的新實(shí)例:

let p1 = Promise.any([]) let p2.catch(err => {}) setTimeout(console.log, 0, p1) // Promise {<rejected>: AggregateError: All promises were rejected}

只要可迭代對(duì)象里包含任何一個(gè) fulfilled 狀態(tài)的 Promise,則會(huì)返回第一個(gè) fulfilled 的實(shí)例,并且以它的值作為新實(shí)例的值:

let p = Promise.any([     1,     Promise.reject(2),     new Promise((resolve, reject) => {}),     Promise.resolve(3), ]) setTimeout(console.log, 0, p) // Promise {<fulfilled>: 1}

其他情況下,都會(huì)返回一個(gè) pending 狀態(tài)的實(shí)例:

let p = Promise.any([     Promise.reject(2),     Promise.reject(3),     new Promise((resolve, reject) => {}), ]) setTimeout(console.log, 0, p) // Promise {<pending>: undefined}

WeakRef

我們知道一個(gè)普通的引用(默認(rèn)是強(qiáng)引用)會(huì)將與之對(duì)應(yīng)的對(duì)象保存在內(nèi)存中。只有當(dāng)該對(duì)象沒(méi)有任何的強(qiáng)引用時(shí),JavaScript 引擎 GC  才會(huì)銷毀該對(duì)象并且回收該對(duì)象所占的內(nèi)存空間。

WeakRef 對(duì)象允許你保留對(duì)另一個(gè)對(duì)象的弱引用,而不會(huì)阻止被弱引用的對(duì)象被 GC 回收。WeakRef 的實(shí)例方法 deref() 可以返回當(dāng)前實(shí)例的  WeakRef 對(duì)象所綁定的 target 對(duì)象,如果該 target 對(duì)象已被 GC 回收則返回 undefined:

let person = { name: '布蘭', age: 12 } let wr = new WeakRef(person) console.log(wr.deref())   // { name: '布蘭', age: 12 }

?正確使用 WeakRef 對(duì)象需要仔細(xì)的考慮,最好盡量避免使用。這里面有諸多原因,比如:GC 在一個(gè) JavaScript 引擎中的行為有可能在另一個(gè)  JavaScript 引擎中的行為大相徑庭,或者甚至在同一類引擎,不同版本中 GC 的行為都有可能有較大的差距。GC 目前還是 JavaScript  引擎實(shí)現(xiàn)者不斷改進(jìn)和改進(jìn)解決方案的一個(gè)難題。?

參考:

  • WeakRef

  • 內(nèi)存管理

邏輯賦值符

邏輯賦值符包含 3 個(gè):

  • x &&= y:邏輯與賦值符,相當(dāng)于 x && (x = y)

  • x ||= y:邏輯或賦值符,相當(dāng)于 x || (x = y)

  • x ??= y:邏輯空賦值符,相當(dāng)于 x ?? (x = y)

看如下示例,加深理解:

let x = 0 x &&= 1  // x: 0 x ||= 1  // x: 1 x ??= 2  // x: 1  let y = 1 y &&= 0     // y: 0 y ||= null  // y: null y ??= 2     // y: 2

數(shù)值分隔符(_)

對(duì)于下面一串?dāng)?shù)字,你一眼看上去不確定它到底是多少吧?

const num = 1000000000

那現(xiàn)在呢?是不是可以很清楚的看出來(lái)它是 10 億:

const num = 1_000_000_000

數(shù)值分隔符(_)的作用就是為了讓數(shù)值的可讀性更強(qiáng)。除了能用于十進(jìn)制,還可以用于二級(jí)制,十六進(jìn)制甚至是 BigInt 類型:

let binarary = 0b1010_0001_1000_0101 let hex = 0xA0_B0_C0 let budget = 1_000_000_000_000n

使用時(shí)必須注意 _ 的兩邊必須要有類型的數(shù)值,否則會(huì)報(bào)錯(cuò),以下這些都是無(wú)效的寫法:

let num = 10_ let binarary = 0b1011_ let hex = 0x_0A0B let budget = 1_n

感謝各位的閱讀,以上就是“ES6實(shí)用方法有哪些”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)ES6實(shí)用方法有哪些這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI