浅谈目前可以使用ES10的5个新特性
ECMAScript2015,也称为ES6,是一个花了6年时间完成的主要版本。从那时起,负责ECMAScript标准开发的技术委员会39(TC39)每年都会发布该标准的新版本。这个年度发布周期简化了这个过程,并使新特性快速可用,JavaScript社区对此表示欢迎。
今年,ECMAScript2019(简称ES2019)将会发布。新功能包括Object.fromEntries(),trimStart(),trimEnd(),flat(),flatMap(),symbol对象的description属性,可选的catch绑定等。
好消息是这些功能已经在最新版本的Firefox和Chrome中实现,并且它们也可以被转换,以便旧版浏览器能够处理它们。
1.Object.fromEntries()
在JavaScript中,将数据从一种格式转换为另一种格式非常常见。为了便于将对象转换为数组,ES2017引入了Object.entrie()方法。此方法将对象作为参数,并以[key,value]的形式返回对象自己的可枚举字符串键控属性对的数组。例如:
constobj={one:1,two:2,three:3}; console.log(Object.entries(obj)); //=>[["one",1],["two",2],["three",3]]
但是如果我们想要做相反的事情并将键值对列表转换为对象呢?某些编程语言(如Python)为此提供了dict()函数。在Underscore.js和Lodash中还有_.fromPairs函数。
ES2019引入Object.fromEntries()方法为JavaScript带来类似的功能,此静态方法允许你轻松地将键值对列表转换为对象:
constmyArray=[['one',1],['two',2],['three',3]]; constobj=Object.fromEntries(myArray); console.log(obj);//=>{one:1,two:2,three:3}
如你所见,Object.fromEntries()与Object.entries()所做的事情正好相反。虽然以前可以实现Object.fromEntries()相同的功能,但它实现方式有些复杂:
constmyArray=[['one',1],['two',2],['three',3]]; constArray.from(myArray).reduce((acc,[key,val]) =>Object.assign(acc,{[key]:val}),{}) console.log(obj);//=>{one:1,two:2,three:3}
请记住,传递给Object.fromEntries()的参数可以是实现可迭代协议的任何对象,只要它返回一个两元素,类似于数组的对象即可。
例如,在以下代码中,Object.fromEntries()将Map对象作为参数,并创建一个新对象,其键和对应值由Map中的对给出:
constmap=newMap(); map.set('one',1); map.set('two',2); constobj=Object.fromEntries(map); console.log(obj);//=>{one:1,two:2}
Object.fromEntries()方法对于转换对象也非常有用,思考以下代码:
constobj={a:4,b:9,c:16}; //将对象转换为数组 constarr=Object.entries(obj); //计算数字的平方根 constmap=arr.map(([key,val])=>[key,Math.sqrt(val)]); //将数组转换回对象 constobj2=Object.fromEntries(map); console.log(obj2);//=>{a:2,b:3,c:4}
上述代码将对象中的值转换为其平方根。为此,它首先将对象转换为数组,然后使用map()方法获取数组中值的平方根,结果是可以转换回对象的数组。
使用Object.fromEntries()的另一种情况是处理URL的查询字符串,如本例所示
constparamsString='param1=foo¶m2=baz'; constsearchParams=newURLSearchParams(paramsString); Object.fromEntries(searchParams);//=>{param1:"foo",param2:"baz"}
此代码中,查询字符串将传递给URLSearchParams()构造函数。然后将返回值(即URLSearchParams对象实例)传递给Object.fromEntries()方法,结果是一个包含每个参数作为属性的对象。
Object.fromEntries()方法目前是第4阶段提案,这意味着它已准备好包含在ES2019标准中。
2.trimStart()andtrimEnd()
trimStart()和trimEnd()方法在实现与trimLeft()和trimRight()相同。这些方法目前处于第4阶段,将被添加到规范中,以便与padStart()和padEnd()保持一致,来看一些例子:
conststr="string"; //es2019 console.log(str.trimStart());//=>"string" console.log(str.trimEnd());//=>"string" //相同结果 console.log(str.trimLeft());//=>"string" console.log(str.trimRight());//=>"string"
对于Web兼容性,trimLeft()和trimRight()将保留为trimStart()和trimEnd()的别名。
3.flat()andflatMap()
flat()方法可以将多维数组展平成一维数组
constarr=['a','b',['c','d']]; constflattened=arr.flat(); console.log(flattened);//=>["a","b","c","d"]
以前,我们经常使用reduce()或concat()来展平多维数组:
constarr=['a','b',['c','d']]; constflattend=[].concat.apply([],arr); //or //constflattened=[].concat(...arr); console.log(flattened);//=>["a","b","c","d"]
请注意,如果提供的数组中有空值,它们会被丢弃:
constarr=['a',,,'b',['c','d']]; constflattened=arr.flat(); console.log(flattened);//=>["a","b","c","d"]
flat()还接受一个可选参数,该参数指定嵌套数组应该被展平的级别数。如果未提供参数,则将使用默认值1:
constarr=[10,[20,[30]]]; console.log(arr.flat());//=>[10,20,[30]] console.log(arr.flat(1));//=>[10,20,[30]] console.log(arr.flat(2));//=>[10,20,30]
flatMap()方法将map()和flat()组合成一个方法。它首先使用提供的函数的返回值创建一个新数组,然后连接该数组的所有子数组元素。来个例子:
constarr=[4.25,19.99,25.5]; console.log(arr.map(value=>[Math.round(value)])); //=>[[4],[20],[26]] console.log(arr.flatMap(value=>[Math.round(value)])); //=>[4,20,26]
数组将被展平的深度级别为1.如果要从结果中删除项目,只需返回一个空数组:
constarr=[[7.1],[8.1],[9.1],[10.1],[11.1]]; //donotincludeitemsbiggerthan9 arr.flatMap(value=>{ if(value>=10){ return[]; }else{ returnMath.round(value); } }); //returns: //=>[7,8,9]
除了正在处理的当前元素外,回调函数还将接收元素的索引和对数组本身的引用。flat()和flatMap()方法目前处于第4阶段。
4.Symbol对象的description属性
在创建Symbol时,可以为调试目的向其添加description(描述)。有时候,能够直接访问代码中的description是很有用的。
ES2019中为Symbol对象添加了只读属性description,该对象返回包含Symbol描述的字符串。
letsym=Symbol('foo'); console.log(sym.description);//=>foo sym=Symbol(); console.log(sym.description);//=>undefined //createaglobalsymbol sym=Symbol.for('bar'); console.log(sym.description);//=>bar
5.可选的catch
trycatch语句中的catch有时候并没有用,思考下面代码:
try{ //使用浏览器可能尚未实现的功能 }catch(unused){ //这里回调函数中已经帮我们处理好的错误 }
此代码中的catch回调的信息并没有用处。但这样写是为了避免SyntaxError错误。ES2019可以省略catch周围的括号:
try{ //... }catch{ //.... }
另外:ES2020的String.prototype.matchAll
matchAll()方法是ES2020第4阶段提议,它针对正则表达式返回所有匹配(包括捕获组)的迭代器对象。
为了与match()方法保持一致,TC39选择了“matchAll”而不是其他建议的名称,例如“matches”或Ruby的“scan”。看个简单的例子:
constre=/(Dr\.)\w+/g; conststr='Dr.SmithandDr.Anderson'; constmatches=str.matchAll(re); for(constmatchofmatches){ console.log(match); } //logs: //=>["Dr.Smith","Dr.",index:0,input:"Dr.SmithandDr.Anderson",groups:undefined] //=>["Dr.Anderson","Dr.",index:14,input:"Dr.SmithandDr.Anderson",groups:undefined]
此正则表达式中的捕获组匹配字符“Dr”,后跟一个点和一个空格。\w+匹配任何单词字符一次或多次。并且g标志指示引擎在整个字符串中搜索模式。
之前,必须在循环中使用exec()方法来实现相同的结果,这不是非常有效:
constre=/(Dr\.)\w+/g; conststr='Dr.SmithandDr.Anderson'; letmatches; while((matches=re.exec(str))!==null){ console.log(matches); } //logs: //=>["Dr.Smith","Dr.",index:0,input:"Dr.SmithandDr.Anderson",groups:undefined] //=>["Dr.Anderson","Dr.",index:14,input:"Dr.SmithandDr.Anderson",groups:undefined]
重要的是要注意尽管match()方法可以与全局标志g一起使用来访问所有匹配,但它不提供匹配的捕获组或索引位置。比较以下代码:
constre=/page(\d+)/g; conststr='page2andpage10'; console.log(str.match(re)); //=>["page2","page10"] console.log(...str.matchAll(re)); //=>["page2","2",index:0,input:"page2andpage10",groups:undefined] //=>["page10","10",index:11,input:"page2andpage10",groups:undefined]
总结
在这篇文章中,我们仔细研究了ES2019中引入的几个关键特性,包括Object.fromEntries(),trimStart(),trimEnd(),flat(),flatMap(),symbol对象的description属性以及可选的catch。
尽管一些浏览器还没有完全实现这些特性,但可以使用Babel和其他JavaScript转换器,仍然可以在项目中使用它们。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。