詳解ECMAScript2019/ES10新屬性
每年都有一些新的屬性進(jìn)入ECMA262標(biāo)準(zhǔn),今年發(fā)布的ECMAScript2019/ES10同樣也有很多新的特性,本文將會(huì)挑選一些普通開(kāi)發(fā)者會(huì)用到的新屬性進(jìn)行深入的解讀。
Array.prototype.flat()
The flat() method creates a new array with all sub-array elements concatenated into it recursively up to the specified depth. -- MDN
簡(jiǎn)單來(lái)說(shuō)flat這個(gè)函數(shù)就是按照一定的深度depth將一個(gè)深層次嵌套的數(shù)組拍扁, 例子:
const nestedArr = [1, 2, [3, 4, [5, 6, [7, [8], 9]]], 10] console.log(nestedArr.flat()) // [1, 2, 3, 4, [5, 6, [7, [8], 9]], 10] console.log(nestedArr.flat(2)) // [1, 2, 3, 4, 5, 6, [7, [8], 9], 10] console.log(nestedArr.flat(3)) // [1, 2, 3, 4, 5, 6, 7, [8], 9, 10] console.log(nestedArr.flat(4)) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] console.log(nestedArr.flat(Infinity)) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
由上面的例子可以看出flat會(huì)按照指定的深度depth將一個(gè)數(shù)組扁平化,如果需要將數(shù)組完全拍扁變成一維數(shù)組,則指定depth為無(wú)限大,即是Infinity,相反如果不指定深度,其默認(rèn)值是1。
Array.prototype.flatMap()
The flatMap() method first maps each element using a mapping function, then flattens the result into a new array. It is identical to a map() followed by a flat() of depth 1, but flatMap() is often quite useful, as merging both into one method is slightly more efficient. -- MDN
簡(jiǎn)單來(lái)說(shuō)flatMap等于一個(gè)數(shù)組先調(diào)用完map函數(shù)再調(diào)用flat函數(shù)將其扁平化,扁平化的深度固定為1,先通過(guò)一個(gè)簡(jiǎn)單的例子感受一下:
const myArr = [1, 2, 3] myArr .map(n => [n * n]) // [[1], [4], [9]] .flat() // [1, 4, 9] // 用flatMap可以一步到位 myArr.flatMap(n => [n * n]) // [1, 4, 9]
從上面的例子來(lái)看flatMap如果只是將flat和map做了一個(gè)簡(jiǎn)單的組合好像可有可無(wú),其實(shí)不然,flatMap有個(gè)強(qiáng)大的功能是可以在map的時(shí)候添加和刪除元素,這個(gè)無(wú)論是map還是filter都沒(méi)有這個(gè)功能。
要想刪除某一個(gè)元素只需要在mapper函數(shù)里面返回一個(gè)空的數(shù)組[], 而增加元素只需在mapper函數(shù)里面返回一個(gè)長(zhǎng)度大于1的數(shù)組,具體可以看下面的例子:
// 假如我們想要?jiǎng)h除掉原數(shù)組里面所有的負(fù)數(shù),同時(shí)將單數(shù)轉(zhuǎn)換為一個(gè)復(fù)數(shù)和1
const a = [5, 4, -3, 20, 17, -33, -4, 18]
// |\ \ x | | \ x x |
// [4,1, 4, 20, 16,1, 18]
a.flatMap(n =>
(n < 0) ? []: // 刪除負(fù)數(shù)
(n % 2 == 0) ? [n] : // 保留復(fù)數(shù)
[n - 1, 1] // 單數(shù)變?yōu)橐粋€(gè)復(fù)數(shù)和1
)
// [4, 1, 4, 20, 20, 16, 1, 18]
Object.fromEntries()
The Object.fromEntries() method transforms a list of key-value pairs into an object. --MDN
fromEntries方法將一個(gè)iterable對(duì)象返回的一系列鍵值對(duì)(key-value pairs)轉(zhuǎn)換為一個(gè)object。先看一個(gè)簡(jiǎn)單的例子理解一下:
// key-value pairs數(shù)組
const entriesArr = [['k1', 1], ['k2', 2]]
console.log(Object.fromEntries(entriesArr)
// {k1: 1, k2: 2}
const entriesMap = new Map([
['k1', 1],
['k2', 2]
]) // {"k1" => 1, "k2" => 2}
console.log(Object.fromEntries(entriesMap))
// {k1: 1, k2: 2}
再來(lái)看一個(gè)自定義的iterable對(duì)象例子深入理解一下:
const iteratorObj = {
[Symbol.iterator]: function () {
const entries = [['k1', 1], ['k2', 2]]
let cursor = 0
return {
next() {
const done = entries.length === cursor
return {
value: done ? undefined : entries[cursor++],
done
}
}
}
}
}
Object.fromEntries(iteratorObj) // {k1: 1, k2: 2}
這個(gè)方法有一個(gè)用途就是對(duì)object的key進(jìn)行filter,舉個(gè)例子:
const studentMap = {
student1: {grade: 80},
student2: {grade: 50},
student3: {grade: 100}
}
const goodStudentMap = Object.fromEntries(
Object
.entries(studentMap)
.filter(([_, meta]) => meta.grade >= 60)
)
console.log(goodStudentMap)
// {student1: {grade: 80}, student3: {grade: 100}}
String.prototype.trimStart
這個(gè)方法很簡(jiǎn)單,就是返回一個(gè)將原字符串開(kāi)頭的空格字符去掉的新的字符串,例子:
const greeting = ' Hello world! ' console.log(greeting.trimStart()) // 'Hello world! '
這個(gè)方法還有一個(gè)別名函數(shù),叫做trimLeft,它們具有一樣的功能。
String.prototype.trimEnd
這個(gè)方法和trimStart類(lèi)似,只不過(guò)是將原字符串結(jié)尾的空格字符去掉,例子:
const greeting = ' Hello world! ' console.log(greeting.trimEnd()) // ' Hello world!'
這個(gè)方法也有一個(gè)別名函數(shù),叫做trimRight, 它們也具有一樣的功能。
Symbol.prototype.description
The read-only description property is a string returning the optional description of Symbol objects. -- MDN
ECMAScript2019給Symbol對(duì)象添加了一個(gè)可選的description屬性,這個(gè)屬性是個(gè)只讀屬性,看看例子:
console.log(Symbol('desc').description)
// desc
console.log(Symbol.for('desc').description)
// desc
// 一些內(nèi)置的Symbol也有這個(gè)屬性
console.log(Symbol.iterator.description)
// Symbol.iterator
// 如果初始化時(shí)沒(méi)有帶description,這個(gè)屬性會(huì)返回一個(gè)undefined,因?yàn)檫@樣才說(shuō)這個(gè)屬性是可選的
console.log(Symbol().description)
// undefined
// 這個(gè)屬性是只讀的,不能被設(shè)置
Symbol.iterator.description = 'mess it'
console.log(Symbol.iterator.description)
// Symbol.iterator
這個(gè)新的屬性只要是為了方便開(kāi)發(fā)者調(diào)試,不能通過(guò)比較兩個(gè)Symbol對(duì)象的description來(lái)確定這兩個(gè)Symbol是不是同一個(gè)Symbol:
var s1 = Symbol("desc")
var s2 = Symbol("desc")
console.log(s1.description === s2.description)
// true
console.log(s1 === s2)
// false
try catch optional binding
ECMAScript2019之后,你寫(xiě)try...catch時(shí)如果沒(méi)必要時(shí)可以不用聲明error:
// ECMAScript2019之前,你一定要在catch里面聲明error,否則會(huì)報(bào)錯(cuò)
try {
...
} catch (error) {
}
// 可是有時(shí)候,你確實(shí)用不到這個(gè)error對(duì)象,于是你會(huì)寫(xiě)這樣的代碼
try {
...
} catch (_) {
...
}
// ECMAScript2019后,你可以直接這樣寫(xiě)了
try {
...
} catch {
...
}
雖然這個(gè)新屬性可以讓你省略掉error,可是我覺(jué)得開(kāi)發(fā)者應(yīng)該避免使用這個(gè)屬性,因?yàn)樵谖铱磥?lái)所有的錯(cuò)誤都應(yīng)該被處理,至少應(yīng)該被console.error出來(lái),否則可能會(huì)有一些潛在的bug,舉個(gè)例子:
let testJSONObj
try {
testJSONObj = JSON.prase(testStr)
} catch {
testJSONObj = {}
}
console.log(testJSONObj)
以上代碼中無(wú)論testStr是不是一個(gè)合法的JSON字符串,testJSONObj永遠(yuǎn)都是一個(gè)空對(duì)象,因?yàn)镴SON.parse函數(shù)名寫(xiě)錯(cuò)了,而你又忽略了錯(cuò)誤處理,所以你永遠(yuǎn)不會(huì)知道這個(gè)typo。
穩(wěn)定的排序 Array.prototype.sort
ECMAScript2019后Array.sort一定是個(gè)穩(wěn)定的排序。什么是穩(wěn)定排序?所謂的穩(wěn)定排序就是:假如沒(méi)排序之前有兩個(gè)相同數(shù)值的元素a[i]和a[j],而且i在j前面,即i < j,經(jīng)過(guò)排序后元素a[i]依然排在a[j]元素的前面,也就是說(shuō)穩(wěn)定的排序不會(huì)改變?cè)瓉?lái)數(shù)組里面相同數(shù)值的元素的先后關(guān)系??磦€(gè)例子:
var users = [
{name: 'Sean', rating: 14},
{name: 'Ken', rating: 14},
{name: 'Jeremy', rating: 13}
]
users.sort((a, b) => a.rating - b.rating)
// 非穩(wěn)定的排序結(jié)果可能是
// [
// {name: 'Jeremy', rating: 13},
// {name: 'Ken', rating: 14},
// {name: 'Sean', rating: 14}
// ]
// 雖然Sean和Ken具有同樣的rating,可是非穩(wěn)定的排序不能保證他們兩個(gè)的順序在排序后保持不變
// ECMAScript2019后,Array.sort將是一個(gè)穩(wěn)定的排序,也就是說(shuō)它可以保證Sean和Ken兩個(gè)人的順序在排序后不變
// [
// {name: 'Jeremy', rating: 13},
// {name: 'Sean', rating: 14},
// {name: 'Ken', rating: 14}
// ]
改進(jìn)Function.prototype.toString()
ECMAScript2019之前,調(diào)用function的toString方法會(huì)將方法體里面的空格字符省略掉,例如:
function hello() {
console.log('hello word')
}
console.log(hello.toString())
//'function hello() {\nconsole.log('hello word')\n}'
ECMAScript2019之后,要求一定要返回函數(shù)源代碼(保留空格字符)或者一個(gè)標(biāo)準(zhǔn)的占位符例如native code,所以ECMAScript2019之后,以上的輸出會(huì)變?yōu)椋?br />
console.log(hello.toString())
//"function hello() {
// console.log('hello word')
//}"
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JS當(dāng)前頁(yè)面登錄注冊(cè)框,固定DIV,底層陰影的實(shí)例代碼
下面小編就為大家?guī)?lái)一篇JS當(dāng)前頁(yè)面登錄注冊(cè)框,固定DIV,底層陰影的實(shí)例代碼。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-09-09
JavaScript語(yǔ)言中的Literal Syntax特性分析
JavaScript語(yǔ)言中的Literal Syntax特性分析...2007-03-03

