我们很难及时得知JavaScript(ECMAScript)中的最新功能,同时找到相关的示例代码更加困难。
为了解决这个问题,我将在本文中介绍在ES2016,ES2017和ES2018(最终草案)中添加的18个功能,这些功能在TC39’s finished proposals中列出,并展示相关的例子。
尽管这篇文章很长,不过应该很容易读懂。 你可以把它想象成“Netflix binge reading”。到此为止,我保证你将对所有这些功能有很多了解。
接下来逐一讨论这些问题。
1. Array.prototype.includes
includes是Array上的一个简单实例方法,能帮助我们轻松查找某项是否存在于数组中(处理 NaN的方式与 indexOff不同)。
(ECMAScript 2016 or ES7 — Array.prototype.includes())
小细节: 在 JavaScript 规范中人们想要把这个方法命名为 contains , 但是这个 名字已经被 Mootools 使用了,所以只好被命名为 includes 。
2. 幂运算符
加法和减法等数学运算分别对应 +和 -运算符。 同样,运算符通常用于指数运算。 在ECMAScript 2016中,引入来代替Math.pow。
(ECMAScript 2016 or ES7 — 幂运算符**)
1. Object.values()
Object.values()是一个与Object.keys()类似的新函数,不过它返回的是Object自身属性的所有值,不包括原型链中的任何值。
(ECMAScript 2017 (ES8)— Object.values())
2. Object.entries()
Object.entries()与Object.keys相关,但它并不是仅返回键,而是以数组方式返回键和值。 这样一来,在循环中使用对象或将对象转换为Maps等操作将会变得非常简单。
Example 1:
(ECMAScript 2017 (ES8) — 在循环中使用 Object.entries())
Example 2:
(ECMAScript 2017 (ES8) — 使用 Object.entries()将 Object转化为 Map)
3.字符串填充
String 中添加了两个实例方法—— String.prototype.padStart和String.prototype.padEnd,允许将空字符串或其他字符串附加/前置到原始字符串的开头或结尾。
'someString'.padStart(numberOfCharcters[,stringForPadding]);
'5'.padStart(10) // ' 5'
'5'.padStart(10, '=*') //'=*=*=*=*=5'
'5'.padEnd(10) // '5 '
'5'.padEnd(10, '=*') //'5=*=*=*=*='
可以在想要用漂亮的格式打印输出时或者打印对齐等场景中派上用场。
3.1 padStart 示例:
下面的示例中列出了不同长度的数字。 我们希望前置“0”,以便在显示时所有项目都具有相同的10位长度。 使用padStart(10, '0')轻松实现这一目标。
(ECMAScript 2017 — padStart示例)
3.2 padEnd 示例:
当我们打印不同长度的多个项目并希望它们正确对齐时,padEnd真的很方便。
下面的示例是padEnd,padStart和Object.entries如何组合在一起以产生漂亮输出的一个很好的现实示例。
(ECMAScript 2017 — padEnd, padStart和 Object.Entries示例)
3.3 使用padStart 与 padEnd 处理 Emojis 和其它双字节字符
Emojis和其他双字节字符使用多个字节的unicode表示。 所以padStart和padEnd可能无法按预期工作!
例如:假设我们想要在字符串中填充10个表情符号,结果如下所示:
//Notice that instead of 5 hearts, there are only 2 hearts and 1 heart that looks odd!
'heart'.padStart(10, ""); // prints.. 'heart'
这是因为的长度是2个码点('\ u2764 \ uFE0F')! 单词heart本身是5个字符,所以我们只剩下5个字符来填充。 所以会发生什么事情,JS使用'\ u2764 \ uFE0F'来填充两颗心并产生。 对于最后一个,它只使用第一个码点\ u2764产生字符。
所以我们最终得到:heart
PS:可以通过此链接(https://encoder.internetwache.org/#tab_uni)查看怎样对unicode char进行转换。
4. Object.getOwnPropertyDescriptors
此方法返回给定对象的所有属性的全部详细信息(包括getter方法 get和 setter方法 set)。 添加它的主要目的是允许浅层拷贝/克隆对象到另一个对象,该对象也复制getter和setter函数而不是Object.assign。
Object.assign用于浅层拷贝除了原始源对象的getter和setter函数之外的所有细节。
下面的示例显示了Object.assign和Object.getOwnPropertyDescriptors以及Object.defineProperties之间的区别,以将原始对象Car复制到新对象ElectricCar中。 你将看到,通过使用Object.getOwnPropertyDescriptors,discount的getter和setter函数也会复制到目标对象中。
以前
(以前 — 使用 Object.assign)
之后
(ECMAScript 2017 (ES8) — Object.getOwnPropertyDescriptors)
5.在函数参数中添加尾随逗号
这是一个次要更新,允许我们在最后一个函数参数后面有逗号。 为什么? 帮助使用像git blame这样的工具来确保只有新的开发人员的代码被标注。
以下示例显示了问题和解决方案。
注意:也可以使用尾随逗号调用函数!
6. Async/Await
到目前为止,这是最重要和最有用的功能。 异步函数允许我们不必处理回调并使整个代码看起来很简单。
async关键字告诉JavaScript编译器以不同方式处理函数。 只要到达该函数中的await关键字,编译器就会暂停。 它假定await之后的表达式返回一个promise并等待,直到promise被解决或被拒绝,然后才进一步移动。
在下面的示例中,getAmount函数调用两个异步函数getUser和getBankBalance。 我们可以做到这一点,但是使用async await更加优雅和简单。
(ECMAScript 2017 (ES 8) — Async Await 基本示例)
6.1异步函数本身返回一个Promise。
如果您正在等待异步函数的结果,则需要使用Promise的then语法来捕获其结果。
在以下示例中,我们希望使用console.log而不是在doubleAndAdd函数中记录结果。 所以我们想等待并使用then语法将结果传递给console.log。
(ECMAScript 2017 (ES 8) — Async Await themselves returns Promise)
6.2 并行调用 async/await
在前面的例子中,我们调用了两次await,每次会等待一秒钟(总共2秒)。 不过我们可以并行化处理它,因为a和b不使用Promise.all相互依赖。
6.3 async/await错误处理功能
使用异步等待时,有多种方法可以处理错误。
选项1 - 在函数中使用try catch
(ECMAScript 2017 - 在async/await函数中使用try catch)
选项2-捕获每个等待表达式
由于每个await表达式都返回一个Promise,因此可以捕获每行的错误,如下所示。
(ECMAScript 2017 — Use try catch every await expression)
选项3 - 捕获整个async-await函数
(ECMAScript 2017 — Catch the entire async/await function at the end)
ECMAScript 2016,2017和2018中所有新功能的示例(下)
(明日继续)