![前端开发必知必会:从工程核心到前沿实战](https://wfqqreader-1252317822.image.myqcloud.com/cover/889/41202889/b_41202889.jpg)
1.3 ES规范
截止到2021年3月9日,EcmaScript规范(简称ES规范)已经发布到2021版的候选版本,该版本包含了几个实用的特性。本节我们总结一下从ES2021到ES2017各个规范的新增特性,便于大家综合参考。
1.3.1 ES2021规范
(1)String.prototype.replaceAll:在replaceAll方法出现之前,字符串替换可以使用replace配合正则表达式的方式,看下面两个例子。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_34_1.jpg?sign=1739490136-Sxnj1DPFODtsNoLyXGhq2bYQLIivTnIC-0-94e34ecef55cd40608291ec2019c1656)
上面的代码可以将所有的b替换成下画线,如果不加正则表达式,则只替换第一个字符。下面使用replaceAll实现相同的功能:
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_34_2.jpg?sign=1739490136-6PLAf1Lka9nlWoCCzCSxD3Xr88kSNOqz-0-7270166708a91143dc2d9a6ff08cfd11)
使用新API后,好处有两点:代码的可读性更好,特殊符号不需要再转义。
(2)逻辑赋值运算符。逻辑赋值运算符结合了逻辑运算符和赋值表达式。逻辑赋值运算符有三种:||=、&&=和??=,如表1-1所示。
表1-1
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_34_3.jpg?sign=1739490136-YocpTRLa2l0llsKAZz0K8PmL5Ti7dLUj-0-01424d0ff8b572f6c54325adaad01a35)
逻辑赋值运算符同样遵守逻辑短路(Short-circuiting)。当将逻辑操作与赋值组合起来时,因为赋值可能会导致副作用,所以赋值操作应该是在某种条件下才进行的。因为副作用会对程序的性能甚至正确性产生负面影响。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_34_4.jpg?sign=1739490136-yepDTmo3IghiJ5kPKP0F7WJu61zJkj5E-0-3be35fde5d1819e25b10ae39f01dd7f9)
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_35_1.jpg?sign=1739490136-Jkn06UFyrGVatO03iWNVDHwRG3YnWDBQ-0-033e02b96b1b0c4918748cd44b5ca791)
(3)WeakRef。通常来说,对JavaScript对象的引用都是强引用。也就是说,一旦保持对某个对象的引用,这个对象就不会被垃圾回收。但是在ES6中引入了WeakMap和WeakSet,这两者中的对象都是弱引用,垃圾回收机制不考虑WeakSet和WeakMap对集合中对象的引用,只要这些对象不再被引用,垃圾回收机制就会自动回收该对象的内存,不考虑该对象是否还存在于Weak集合中。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_35_2.jpg?sign=1739490136-1ljuHdlMLHSspHKCyRGJLeYJwX4Nr3Fw-0-4d48b06294e3e0d212192ddcb8dfed3e)
此时,在该代码块中不再保持对对象ref的引用,垃圾回收机制随时可以对它进行回收。
WeakMap和WeakSet不是真正的弱引用,只要key是活动的,还是会保持强引用。一旦key被垃圾回收,则Weak集合仅弱引用其内容。
WeakRef是一个高级API,它提供了真正的弱引用,允许创建对象的弱引用,当跟踪现有对象时不会阷止对其进行垃圾回收,这对于缓存和对象映射非常有用。当浏览器需要进行垃圾回收时,如果对该对象的唯一引用来自WeakRef变量,则JavaScript引擎可以安全地从内存中初除该对象并释放空间。下面的代码是使用WeakRef构造方法构造的一个实例,然后通过实例的deref方法访问变量。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_35_3.jpg?sign=1739490136-LOrpV42YcjyEZDPC020yL5Rp10rHITsP-0-f66bf7fd399606fbe5c2492a4e36cd95)
FinalizationRegistry接收一个注册器回调函数,可以利用该注册器为挃定对象注册一个事件监听器。在对象被垃圾回收之后,会触发监听的事件。首先,创建一个注册器:
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_36_1.jpg?sign=1739490136-YWZUqVYHMyRpiT2MOg1PPa4ylfbZLGEa-0-eaaff706191164120b8105e0424d2773)
接着,注册一个挃定对象,同时挃定给注册器回调传递的参数。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_36_2.jpg?sign=1739490136-fHGl1jLQUCYLe7FSyJ3QrsLWsvQpxvNt-0-6ba0cd8da26d2e877ac365c4f599c1cb)
(4)数字分隑符。数字分隑符提供了一种使大数字更易于阅读和使用的简单方法:
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_36_3.jpg?sign=1739490136-uBuJLpBM06hi1Ra7Fis1i9vRcoKAcyyM-0-04aa0ddc00ce3f04c7091347ef7d7457)
(5)Promise.any。接收几个promise对象,只要其中任意一个成功,就返回那个成功的promise对象。如果所有的promise对象都失败,就返回一个失败的promise对象。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_36_4.jpg?sign=1739490136-ZKyQRdc0knEC0dybqSqnqBOd44VzB6Ic-0-514dd91796d292d30d01acf2fa4b790d)
下面对Promise.all和Promise.race做一个简单对比。
Promise.all:只要有一个promise对象失败,就返回失败;只有所有的promise对象都成功,才返回成功。Promise.race:只要有一个promise对象状态发生改变,就返回该promise对象。
1.3.2 ES2020规范
(1)String.protype.matchAll。matchAll方法可返回一个正则表达式在字符串的所有匹配。下面先实现一个例子,即匹配十六进制的字符。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_37_1.jpg?sign=1739490136-QrdlvHXremwHj2ismLNYlD4lRlfABMMX-0-1058f141aeb7ab7cfe6c369ff4abcc41)
返回结果如下。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_37_2.jpg?sign=1739490136-65WgkwKk3spGuLmpyNXaKu6hAqfwFbDx-0-b4013ca342c4e6cb4dacd1073822b1c8)
(2)动态导入(dynamic import)。动态导入提供了一种类似函数的新的导入形式,与静态导入相比,有更多的新功能。
先看一下静态导入。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_37_3.jpg?sign=1739490136-YuznJpeAzHypeWO78RpC0cK8zc4SOD5p-0-d7779345dddc650e81de0cad40156508)
接下来就可以在script中导入了。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_37_4.jpg?sign=1739490136-DPVXjO8mqhIHZCVv1GulkUD2udnLTXgy-0-0be87c9a4ab37b3ef7b2c96c911dd26a)
这种导入模块的语法形式是一个静态声明:它仅接受字符串文字作为模块标识,通过运行前的“链接”过程,引入绑定(bindings)到本地作用域中。静态导入只能在文件的顶层使用。
import(specifier)函数支持动态加载模块。Import函数的参数specifier可以挃定所要加载的模块的位置,并返回promise对象:
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_38_1.jpg?sign=1739490136-paQaUhEB8D4n2MmqRwjUDRFRAR8XXztW-0-01f02e6391845b0a07771cd736518d1b)
(3)BigInt。它提供了一种表示大于253-1的整数的方法,也就是说,可以表示任意大的整数。具体用法是通过在一个整数字面量后面加n的方式定义一个BigInt类型:
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_38_2.jpg?sign=1739490136-iqrS7ixwVJjNOxsjVjdonXLfrKZkg94g-0-0b3aa5337c23c8047cbdea454ed38d83)
(4)Optional Chaining(可选链操作符)。?.运算符被称为链刞断运算符,它允许开发人员读取深度嵌套在对象链中的属性值,而不必验证每个属性是否都存在。当引用为空时,返回undefined。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_38_3.jpg?sign=1739490136-F9nxJsWSI6ILK1Xstgu0a9Ssuduh7vgm-0-12660b21488eacdc7e6f89011002e067)
(5)Nullish coalescing(空位操作符)。??运算符被称为空位操作符。如果第一个参数不是false,则返回第一个参数,否则返回第二个参数。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_39_1.jpg?sign=1739490136-ckgOIZdG0GyjBnhcTIJSHFbFZOcj9D2L-0-ba395f5e3837e00df8c6e36cd0072e23)
(6)globalThis。globalThis可获取不同环境的this,在ES2020规范之前,可以封装一层。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_39_2.jpg?sign=1739490136-W1g0IfUMbQRIyBaUZSXB3eTXSU0N3CUX-0-eaf19eee7e933125ba6173fbb5ec79e0)
现在就可以按照如下方式使用了。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_39_3.jpg?sign=1739490136-EnyRCjrYd9VvhjpOMDyI5b6uuWbLXZQu-0-603562aca668ed26203dcfc11cbb4467)
(7)模块命名空间导出(module namespace export)。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_39_4.jpg?sign=1739490136-kkFNX0tMWq1qSltsrVzCTTgrgK2g0IEj-0-7cb0eaec2fbaf02cacf5b0e5c4da1d6a)
(8)Promise.allSettled。Promise.allSettled接受一组promise,返回新的promise实例,并且所有这些参数实例都会返回结果,不管fulfilled状态还是rejected状态。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_39_5.jpg?sign=1739490136-1mZTC3TPynfEW6NTOPK07tl5tm1xBKwz-0-c39afbf668393aa9a2be693b447c549a)
1.3.3 ES2019规范
(1)Array.flat Array.flatMap:如果数组的成员还是数组,则flat方法可以将嵌套的数组“拉平”,变成一维数组。该方法返回一个新数组,对原始数据没有影响。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_40_1.jpg?sign=1739490136-vkeJyZUVRaKckYE6KaU8Erz8k3Um0ZO3-0-27c0a8cd11c33914f192be907e39279f)
flatMap()只能展开一维数组。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_40_2.jpg?sign=1739490136-VQxriI9W6bJGqAG2v0Gdg5Pm45jNb8bb-0-0420655ef8936b53ff7cbc7d1c1081f4)
(2)Object.fromEntries:将键值对数组转为对象。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_40_3.jpg?sign=1739490136-UQVQO3o7JSMDCc0KIrdTUbG7cL9h6f8M-0-82bb5e7bc8ec60ab075eabd424a4468d)
(3)String.trimStart和String.trimEnd:trimStart可去掉字符串头部的空格,trimEnd可去掉字符串尾部的空格。它们都返回新字符串,不影响原始字符串。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_40_4.jpg?sign=1739490136-3fWahExWhBvqis9NTdUkgUraBsOgiYgy-0-eead2a19d7cf31ff4ca77622616f7fa0)
Arrary.sort:稳定排序。在ES2019中规定,排序必须稳定。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_40_5.jpg?sign=1739490136-lgDE1wlSqNENXGotfZE5pLsxaY1da72P-0-1bab032f0bc2e4270c3da7db91387b5f)
(4)JSON.stringfy改造:如果遇到0xD800到0xDFFF之间的单个码点,或者不存在的配对形式,则返回转义字符串。
(5)Symbol description属性:ES2019为Symbol提供了一个实例属性description,可以查看Symbol的描述。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_41_1.jpg?sign=1739490136-qqCFbvTHtm4ttMEUsXwuMX4TRyPqD7lq-0-a89197825297595eb08521be5316176e)
1.3.4 ES2018规范
(1)对象的Rest/Spread:ES6为数组引入了扩展运算符的功能。在ES6中,只有数组有这个特性,从ES2018开始,对象也开始支持这个特性。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_41_2.jpg?sign=1739490136-DWON1ukhXXa7lmU4U9Hwl8QG4qYkeuyV-0-d1c5a591cc2e643eb44b945c772d9a9b)
(2)Promise.finally:该方法用于挃定不管promise对象的最后状态如何,都会执行的操作。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_41_3.jpg?sign=1739490136-1B07zdeg7vYAK6ty1dl5u4JAmcUH7CgQ-0-ff874b20beb554bf0f2d7b691a417d68)
(3)异步迭代器:循环遍历异步可迭代对象及同步可迭代对象,包括内置的String、Array,以及类似数组对象(例如arguments或NodeList、TypedArray、Map、Set)和用户定义的异步或同步迭代器。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_41_4.jpg?sign=1739490136-g001yQWXsS811ETQ1wvbkjf1ucjd1qtD-0-706014e07fc5cd251f9a51dbb46c82ec)
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_42_1.jpg?sign=1739490136-XDoxXc7Piww8Q8j53hsCFEkDhMomB1my-0-d03c7aff3a04a9a1fbca9a453cf65a05)
正则表达式。ES2018引入s修饰符(dotAll模式),使.可以匹配任意单个字符。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_42_2.jpg?sign=1739490136-4bpa2ReQo1FzElpPrDDeBCkUFRZaEKcR-0-a09824e359e4b73b140a1007be735ad3)
ES2018为正则表达式引入了具名组匹配(Named Capture Groups),为每一组匹配挃定一个名称,既便于阅读代码,又便于引用。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_42_3.jpg?sign=1739490136-Ig1WJQwvw6hkd2GKVR3n54rhwVoy2l1L-0-7290f43f016b537de53d7d666894617d)
1.3.5 ES2017规范
(1)Object.values/Object.entries。Object.values方法返回一个数组,返回对象自身的(不包括继承的)所有可遍历(enumerable)属性的值。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_42_4.jpg?sign=1739490136-8hYm2Exsz5v461bJYln6OYkNvgKTQZja-0-be9b1bba1b614ef67f9a2c9a4509f09c)
Object.entries方法返回一个数组,返回对象自身的(不包括继承的)所有可遍历(enumerable)属性的键值对数组,该方法也适用于数组。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_42_5.jpg?sign=1739490136-OSd1LxRxW60k77bs13vrUEIrQl3MpKZv-0-7337a389213531c1d374405298d9a9ef)
(2)字符串补全。padStart(targetLength [,padString)用于头部补全,padEnd(targetLength [,padString)用于尾部补全。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_43_1.jpg?sign=1739490136-gvI1aQs9AgexMG4AERF4y0VtdT890Y4g-0-71f26afe31604ff54de812792d35a03a)
(3)异步函数(asnyc)。异步函数是promise和generators(生成器)的组合,简化了promise的调用,提高了代码的可读性:
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_43_2.jpg?sign=1739490136-uhIbDxQfYdClfF5cVZZZukLngukU88EL-0-1accc33580ddf604c43a21f8374cd334)
(4)Object.getOwnPropertyDescriptors。该方法返回对象的自身属性,不包括继承的。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_43_3.jpg?sign=1739490136-9UCMoz40vNp1kPUVIt6iR1M8WLMcUQpc-0-40b7feac727a714a29538aa650710ce4)