作者|rajaraodv
译者|无知
跟踪 JavaScript (ECMAScript) 提供的新功能并不容易,找到有用的代码示例就更难了。 在本文中,我描述了 ES2016、ES2017 和 ES2018 中添加的 18 个功能,并提供了有用的示例。
ECMAScript 2016
1. Array.prototype.includes
include 是一种数组方法,用于查找字段是否包含某个项目(与 indexOf 不同,它可以包含 NaN)。
2. 指数中缀运算符
加法和除法等物理运算分别具有中缀运算符,例如 + 和 - 。 类似地,中缀运算符通常用于求幂。 在 ECMAScript 2016 中引入以取代 Math.pow。
ECMAScript 2017
1. 对象。 值()
Object.values()是一个类似于Object.keys()的新函数,它返回Object的所有属性的值,不包括原型链中的属性。
2. 对象。 条目()
Object.entries() 与 Object.keys 相关,但它不是返回键,而是以链表的形式返回键和值。 这使得在循环中使用对象或将对象转换为映射之类的事情变得非常容易。
示例1:
示例2:
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') 轻松做到这一点。
3.2 padEnd示例:
当我们复制多个不同宽度的项目并希望它们对齐时,使用 padEnd 非常方便。
这是一个很好的现实世界示例,padEnd、padStart 和 Object.entries 组合在一起形成了一个很好的输出。
3.3 对表情符号和其他双字节字符使用 padStart 和 padEnd
表情符号和其他双字节字符使用多个 unicode 字节表示,因此 padStart 和 padEnd 可能难以按预期工作!
示例:假设我们尝试将字符串 heart 填充为最多 10 个字符。 结果如下:
// 请注意,我们看到的不是 5 个心, 而是两个心和一个看起来有点怪的另一个心!
'heart'.padStart(10, "❤️"); // prints.. '❤️❤️❤heart'
这是因为它需要 2 个代码点 ('u2764uFE0F')! 心本身有 5 个字符,所以我们还剩下 5 个字符来填充。 JS使用'u2764uFE0F'来填充两颗心,生成。 对于最后一个,它是使用心脏的第一个字符 u2764 生成的。
所以我们最终得到:心。
关于unicode字符的转换可以参考:
#tab_uni
4. 对象。 获取自己的属性描述符
此方法返回有关给定对象的所有属性的详细信息(包括 get 和 set 方法)。 添加它的主要动机是允许将一个对象浅复制/克隆到另一个对象,同时还复制 getter 和 setter 函数而不是 Object.assign。
Object.assign 将浅复制除原始源对象的 getter 和 setter 函数之外的所有内容。
以下示例显示了使用 Object.assign 和 Object.getOwnPropertyDescriptors 与 Object.defineProperties 将原始对象 Car 复制到新对象 ElectricCar 之间的区别。 您将看到,通过使用 Object.getOwnPropertyDescriptors,折扣的 getter 和 setter 函数也被复制到目标对象。
前:
后:
5. 在函数参数中添加尾随冒号
这是一个小更新ecmascript 运算符,允许在最后一个函数参数之前使用冒号。
以下示例显示了问题和解决方案。
注意:您还可以调用带有尾随冒号的函数!
6. 异步/等待
这是迄今为止最重要和最有用的功能。 异步函数可以防止反弹地狱并使整体代码看起来更简单。
async 关键字告诉 JavaScript 编译器以不同的方式对待该函数。 每当编译器在函数中遇到await关键字时,编译器都会暂停。 它假设await 之后的表达式返回一个promise,并等待直到promise 满足或被拒绝。
在下面的示例中,getAmount 函数调用两个异步函数 getUser 和 getBankBalance。 我们可以使用 Promise,但 async wait 更柔和、更简单。
6.1 返回 Promise 的异步函数
如果想要获取异步函数返回的结果,需要使用Promise的then语法来捕获结果。
在下面的示例中,我们希望使用 console.log 来记录结果(但不在 doubleAndAdd 中)。 因此,我们需要等待并使用 then 语法将结果传递到 console.log。
6.2 并行调用async/await
在上面的反例中,我们调用了两次await,每次等待一秒(总共2秒)。 实际上我们可以并行调用await,因为a和b互不依赖。
6.3 async/await 函数的错误处理
使用 async/await 时有多种方法可以处理错误。
选项 1 - 在函数内使用 try catch
选项 2 - 捕获每个等待表达式
由于每个等待表达式都会返回一个 Promise,因此可以像这样逐行捕获错误。
选项 3 - 捕获整个 async-await 函数
ECMAScript 2018
1.共享显存和原子
这是一个中间功能,是 JS 引擎的核心增强。
主要思想是在JavaScript中引入某种多线程特性,让JS开发者可以自己管理显存,编写高性能并发程序。
这是通过一个名为 SharedArrayBuffer 的全局对象来实现的,该对象本质上将数据存储在共享视频内存中。 因此,这些数据可以在主JS线程和Web工作线程之间共享。
到目前为止,如果我们想在主 JS 线程和 Web Worker 之间共享数据,我们必须复制数据并使用 postMessage 将数据发送到另一个线程。 但那就没有这个必要了!
您只需使用 SharedArrayBuffer,主线程和多个 Web 工作线程就可以同时访问共享数据。
但在线程之间共享视频内存可能会导致竞争条件。 为了防止竞争情况,引入了“原子”全局对象。 Atomics提供了多种在线程使用数据时锁定共享显存的方法,还提供了安全更新共享显存数据的方法。
建议通过库来使用该功能,但目前还没有基于该功能的库。
2.去除标签模板字面量限制
首先,我们需要澄清什么是“标记模板文字”,以便更好地理解此功能。
在 ES2015+ 中,有一个称为标记模板文字的功能,允许开发人员自定义字符串的对齐方式。 例如,如果使用标准形式,则字符串插值如下所示:
在标记文字中,您可以编写一个函数,该函数采用硬编码字符串文字(例如 [ 'Hello ', '!' ])和替换变量(例如 ['Raja'] ),这些变量作为定义函数的参数传递(例如问候)并从自定义函数中返回您想要的任何内容。
以下示例显示我们的自定义函数greet 添加了“早上好!”
现在我们已经介绍了什么是“标记”功能,许多人希望在不同的地方使用此功能,例如命令行终端和编译 HTTP 请求的 URI 等。
标记字符串文字的问题
问题是 ES2015 和 ES2016 规范不允许转义字符ecmascript 运算符,如“u”(unicode)、“x”(十六进制),除非它们看起来像 u00A9 或 u{2F804} 或 xA9 。
如果您的标记函数在内部使用其他域的规则(例如终端规则),可能需要像 ubla123abla 这样的字符,那么您将收到语法错误。
在 ES2018 中,规则已经放宽,只要标记函数通过具有“cooked”属性(无效字符为“undefined”)和“raw”属性(无论你做什么)的对象返回值,就允许这些无效值。想)。 通配符。
function myTagFunc(str) {
return { "cooked": "undefined", "raw": str.raw[0] }
}
var str = myTagFunc `hi ubla123abla`; //call myTagFunc
str // { cooked: "undefined", raw: "hi \unicode" }
3.“。” 正则表达式的符号
目前,在正则表达式中,虽然点(“.”)可以匹配单个字符,但它不能匹配换行符,例如 n、r、n 等。
例如:
//Before
/first.second/.test('firstnsecond'); //false
此增强功能使点可以匹配任何单个字符。 要正确使用此功能,在创建正则表达式时需要使用 s 标志。
//ECMAScript 2018
/first.second/s.test('firstnsecond'); //true Notice: /s
以下是动议文档中的API概要:
4. RegExp 命名组捕获
此增强功能引入了来自其他语言(例如 Python、Java 等)的一个有用的 RegExp 功能,称为“命名组”。 开发人员可以以 (?…) 的格式为 RegExp 组的不同部分指定名称(标识符)。 然后,他们可以使用标识符轻松获取所需的组。
4.1 基本命名组示例
在下面的示例中,我们使用 (?)、(?) 和 (?) 分别对应日期 RegExp 组的不同部分。 生成的对象将包含一个 groups 属性,该属性又将包含具有相应值的年、月和日属性。
4.2 在正则表达式中使用命名组
我们可以使用 k 来反向引用正则表达式中的组,请参见下面的示例。
4.3 将命名组与 String.prototype.replace 一起使用
现在可以在String的replace实例方法中使用命名组功能,我们可以轻松地交换字符串中的短语。
例如,将“firstName,lastName”更改为“lastName,firstName”。
5. 对象的其余属性
余数运算符...(三个点)允许我们提取尚未提取的对象属性。
5.1 可以使用rest操作符提取你需要的属性
5.2 您还可以删除不需要的项目!
6. 对象的扩展属性
扩展属性看起来有点像其余属性...只不过您使用它们来创建新对象。
提示:展开运算符用在等号的一侧,其余运算符用在等号的左侧。
7. RegExp后向断言
这是对 RegEx 的增强,以确保某些字符串紧邻其他字符串之前。
您现在可以使用组 (?:
活动推荐
今年12月7-8日在北京国际会议中心举办的ArchSummit全球架构师技术大会邀请了100多位国内外专业讲师,并设立了后端技术专题,分享他们最新的黑科技和开发经验。