详解ECMAScript2019/ES10新属性
每年都有一些新的属性进入ECMA262标准,今年发布的ECMAScript2019/ES10同样也有很多新的特性,本文将会挑选一些普通开发者会用到的新属性进行深入的解读。
Array.prototype.flat()
Theflat()methodcreatesanewarraywithallsub-arrayelementsconcatenatedintoitrecursivelyuptothespecifieddepth.--MDN
简单来说flat这个函数就是按照一定的深度depth将一个深层次嵌套的数组拍扁,例子:
constnestedArr=[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会按照指定的深度depth将一个数组扁平化,如果需要将数组完全拍扁变成一维数组,则指定depth为无限大,即是Infinity,相反如果不指定深度,其默认值是1。
Array.prototype.flatMap()
TheflatMap()methodfirstmapseachelementusingamappingfunction,thenflattenstheresultintoanewarray.Itisidenticaltoamap()followedbyaflat()ofdepth1,butflatMap()isoftenquiteuseful,asmergingbothintoonemethodisslightlymoreefficient.--MDN
简单来说flatMap等于一个数组先调用完map函数再调用flat函数将其扁平化,扁平化的深度固定为1,先通过一个简单的例子感受一下:
constmyArr=[1,2,3] myArr .map(n=>[n*n])//[[1],[4],[9]] .flat()//[1,4,9] //用flatMap可以一步到位 myArr.flatMap(n=>[n*n])//[1,4,9]
从上面的例子来看flatMap如果只是将flat和map做了一个简单的组合好像可有可无,其实不然,flatMap有个强大的功能是可以在map的时候添加和删除元素,这个无论是map还是filter都没有这个功能。
要想删除某一个元素只需要在mapper函数里面返回一个空的数组[],而增加元素只需在mapper函数里面返回一个长度大于1的数组,具体可以看下面的例子:
//假如我们想要删除掉原数组里面所有的负数,同时将单数转换为一个复数和1 consta=[5,4,-3,20,17,-33,-4,18] //|\\x||\xx| //[4,1,4,20,16,1,18] a.flatMap(n=> (n<0)?[]://删除负数 (n%2==0)?[n]://保留复数 [n-1,1]//单数变为一个复数和1 ) //[4,1,4,20,20,16,1,18]
Object.fromEntries()
TheObject.fromEntries()methodtransformsalistofkey-valuepairsintoanobject.--MDN
fromEntries方法将一个iterable对象返回的一系列键值对(key-valuepairs)转换为一个object。先看一个简单的例子理解一下:
//key-valuepairs数组
constentriesArr=[['k1',1],['k2',2]]
console.log(Object.fromEntries(entriesArr)
//{k1:1,k2:2}
constentriesMap=newMap([
['k1',1],
['k2',2]
])//{"k1"=>1,"k2"=>2}
console.log(Object.fromEntries(entriesMap))
//{k1:1,k2:2}
再来看一个自定义的iterable对象例子深入理解一下:
constiteratorObj={
[Symbol.iterator]:function(){
constentries=[['k1',1],['k2',2]]
letcursor=0
return{
next(){
constdone=entries.length===cursor
return{
value:done?undefined:entries[cursor++],
done
}
}
}
}
}
Object.fromEntries(iteratorObj)//{k1:1,k2:2}
这个方法有一个用途就是对object的key进行filter,举个例子:
conststudentMap={
student1:{grade:80},
student2:{grade:50},
student3:{grade:100}
}
constgoodStudentMap=Object.fromEntries(
Object
.entries(studentMap)
.filter(([_,meta])=>meta.grade>=60)
)
console.log(goodStudentMap)
//{student1:{grade:80},student3:{grade:100}}
String.prototype.trimStart
这个方法很简单,就是返回一个将原字符串开头的空格字符去掉的新的字符串,例子:
constgreeting='Helloworld!' console.log(greeting.trimStart()) //'Helloworld!'
这个方法还有一个别名函数,叫做trimLeft,它们具有一样的功能。
String.prototype.trimEnd
这个方法和trimStart类似,只不过是将原字符串结尾的空格字符去掉,例子:
constgreeting='Helloworld!' console.log(greeting.trimEnd()) //'Helloworld!'
这个方法也有一个别名函数,叫做trimRight,它们也具有一样的功能。
Symbol.prototype.description
Theread-onlydescriptionpropertyisastringreturningtheoptionaldescriptionofSymbolobjects.--MDN
ECMAScript2019给Symbol对象添加了一个可选的description属性,这个属性是个只读属性,看看例子:
console.log(Symbol('desc').description)
//desc
console.log(Symbol.for('desc').description)
//desc
//一些内置的Symbol也有这个属性
console.log(Symbol.iterator.description)
//Symbol.iterator
//如果初始化时没有带description,这个属性会返回一个undefined,因为这样才说这个属性是可选的
console.log(Symbol().description)
//undefined
//这个属性是只读的,不能被设置
Symbol.iterator.description='messit'
console.log(Symbol.iterator.description)
//Symbol.iterator
这个新的属性只要是为了方便开发者调试,不能通过比较两个Symbol对象的description来确定这两个Symbol是不是同一个Symbol:
vars1=Symbol("desc")
vars2=Symbol("desc")
console.log(s1.description===s2.description)
//true
console.log(s1===s2)
//false
trycatchoptionalbinding
ECMAScript2019之后,你写try...catch时如果没必要时可以不用声明error:
//ECMAScript2019之前,你一定要在catch里面声明error,否则会报错
try{
...
}catch(error){
}
//可是有时候,你确实用不到这个error对象,于是你会写这样的代码
try{
...
}catch(_){
...
}
//ECMAScript2019后,你可以直接这样写了
try{
...
}catch{
...
}
虽然这个新属性可以让你省略掉error,可是我觉得开发者应该避免使用这个属性,因为在我看来所有的错误都应该被处理,至少应该被console.error出来,否则可能会有一些潜在的bug,举个例子:
lettestJSONObj
try{
testJSONObj=JSON.prase(testStr)
}catch{
testJSONObj={}
}
console.log(testJSONObj)
以上代码中无论testStr是不是一个合法的JSON字符串,testJSONObj永远都是一个空对象,因为JSON.parse函数名写错了,而你又忽略了错误处理,所以你永远不会知道这个typo。
稳定的排序Array.prototype.sort
ECMAScript2019后Array.sort一定是个稳定的排序。什么是稳定排序?所谓的稳定排序就是:假如没排序之前有两个相同数值的元素a[i]和a[j],而且i在j前面,即i
varusers=[
{name:'Sean',rating:14},
{name:'Ken',rating:14},
{name:'Jeremy',rating:13}
]
users.sort((a,b)=>a.rating-b.rating)
//非稳定的排序结果可能是
//[
//{name:'Jeremy',rating:13},
//{name:'Ken',rating:14},
//{name:'Sean',rating:14}
//]
//虽然Sean和Ken具有同样的rating,可是非稳定的排序不能保证他们两个的顺序在排序后保持不变
//ECMAScript2019后,Array.sort将是一个稳定的排序,也就是说它可以保证Sean和Ken两个人的顺序在排序后不变
//[
//{name:'Jeremy',rating:13},
//{name:'Sean',rating:14},
//{name:'Ken',rating:14}
//]
改进Function.prototype.toString()
ECMAScript2019之前,调用function的toString方法会将方法体里面的空格字符省略掉,例如:
functionhello(){
console.log('helloword')
}
console.log(hello.toString())
//'functionhello(){\nconsole.log('helloword')\n}'
ECMAScript2019之后,要求一定要返回函数源代码(保留空格字符)或者一个标准的占位符例如nativecode,所以ECMAScript2019之后,以上的输出会变为:
console.log(hello.toString())
//"functionhello(){
//console.log('helloword')
//}"
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。