![前端开发必知必会:从工程核心到前沿实战](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=1739373196-w7MsQhOo3Ig18kzb7TsPTt51woIhDpOv-0-87f8c3495fae9f8a9bfcde69367584d8)
上面的代码可以将所有的b替换成下画线,如果不加正则表达式,则只替换第一个字符。下面使用replaceAll实现相同的功能:
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_34_2.jpg?sign=1739373196-MKhd7Vm8VRlcvzFPuUIT4cUhI7iwEdsR-0-97c7cddbc8993e51245044a351b6cd77)
使用新API后,好处有两点:代码的可读性更好,特殊符号不需要再转义。
(2)逻辑赋值运算符。逻辑赋值运算符结合了逻辑运算符和赋值表达式。逻辑赋值运算符有三种:||=、&&=和??=,如表1-1所示。
表1-1
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_34_3.jpg?sign=1739373196-HuB1iD7IJkpy2MusS1QYjot2ga3LhMj8-0-fd7e0ea7b75ee678a18f35ed69c49d63)
逻辑赋值运算符同样遵守逻辑短路(Short-circuiting)。当将逻辑操作与赋值组合起来时,因为赋值可能会导致副作用,所以赋值操作应该是在某种条件下才进行的。因为副作用会对程序的性能甚至正确性产生负面影响。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_34_4.jpg?sign=1739373196-uQaLQwuS6V98tDPDImQJIJfmocs1VAa6-0-1816eda4e8461e83ad7de1cb821a37a4)
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_35_1.jpg?sign=1739373196-bMLtkczOHUYWI49SR67x3UpBa0hfolNB-0-66fb7959cf4e293f75eaf6143958a0e9)
(3)WeakRef。通常来说,对JavaScript对象的引用都是强引用。也就是说,一旦保持对某个对象的引用,这个对象就不会被垃圾回收。但是在ES6中引入了WeakMap和WeakSet,这两者中的对象都是弱引用,垃圾回收机制不考虑WeakSet和WeakMap对集合中对象的引用,只要这些对象不再被引用,垃圾回收机制就会自动回收该对象的内存,不考虑该对象是否还存在于Weak集合中。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_35_2.jpg?sign=1739373196-IYf2vQmOYzsDwhkMkQDxIHXkHitmxoGG-0-f71d606cca2d7108504b9966ca1838cb)
此时,在该代码块中不再保持对对象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=1739373196-JJULazKHFaTn84VCPMdcn6lymEISizZr-0-9f2d079cd1d8b9b62913cb4e60fb74b5)
FinalizationRegistry接收一个注册器回调函数,可以利用该注册器为挃定对象注册一个事件监听器。在对象被垃圾回收之后,会触发监听的事件。首先,创建一个注册器:
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_36_1.jpg?sign=1739373196-vt91lL0PIUz5N0ia6DWrhWrLgO5Qnfq0-0-8584d17e36c322dc3f5ea8205d2a1ca5)
接着,注册一个挃定对象,同时挃定给注册器回调传递的参数。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_36_2.jpg?sign=1739373196-DNeTCdhGOMJYnIMUvnUCDBbivcTn3LWg-0-acb306eadc7a3d6edc320ca6cb194595)
(4)数字分隑符。数字分隑符提供了一种使大数字更易于阅读和使用的简单方法:
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_36_3.jpg?sign=1739373196-Cetx0cGtUdJyk86AwFwyKQB6P2IvuZbO-0-c2dce0ae6b6a0f960fa010742668270d)
(5)Promise.any。接收几个promise对象,只要其中任意一个成功,就返回那个成功的promise对象。如果所有的promise对象都失败,就返回一个失败的promise对象。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_36_4.jpg?sign=1739373196-0efVh59XLar9nvamJN0rEfSf7qkWO1Jd-0-6ba702aa3ddc4e50ec1b1f62667c25a0)
下面对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=1739373196-tFLe11RCI8Nl4j8dr1NKkWGHEVbZFe4z-0-eb757590650bb3faba2db8d0f9ccf4bf)
返回结果如下。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_37_2.jpg?sign=1739373196-Vmnd15esOeShngvUpDdTMWxJeTRCv1k6-0-760a5f561c0586f0528dd3da786eb3c7)
(2)动态导入(dynamic import)。动态导入提供了一种类似函数的新的导入形式,与静态导入相比,有更多的新功能。
先看一下静态导入。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_37_3.jpg?sign=1739373196-dMvuK9SBbwITtLWfsm7qh9wOHoaZGDUa-0-41e4b48ec223f68687942778274e9f60)
接下来就可以在script中导入了。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_37_4.jpg?sign=1739373196-rykglT4zkKOjv4fP6gaPuIH59HjEHxTP-0-9d239fa09fd95f65197dc0f4fe0146c2)
这种导入模块的语法形式是一个静态声明:它仅接受字符串文字作为模块标识,通过运行前的“链接”过程,引入绑定(bindings)到本地作用域中。静态导入只能在文件的顶层使用。
import(specifier)函数支持动态加载模块。Import函数的参数specifier可以挃定所要加载的模块的位置,并返回promise对象:
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_38_1.jpg?sign=1739373196-9UgYCVkGHX3MyyylkWpzFS2zc17TiCG6-0-9bc5b100e3c62dee2a28476b29800109)
(3)BigInt。它提供了一种表示大于253-1的整数的方法,也就是说,可以表示任意大的整数。具体用法是通过在一个整数字面量后面加n的方式定义一个BigInt类型:
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_38_2.jpg?sign=1739373196-NFhkgIUMw8lfdSag8Vsk5esyBzbJ5otk-0-2a87a7a8e648b42f21e3969b4f64630b)
(4)Optional Chaining(可选链操作符)。?.运算符被称为链刞断运算符,它允许开发人员读取深度嵌套在对象链中的属性值,而不必验证每个属性是否都存在。当引用为空时,返回undefined。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_38_3.jpg?sign=1739373196-aYGjrOqXA0bGl5GnTxqh58WZDVlupif4-0-81f675445e11c34f12cd33b22ddcaeaa)
(5)Nullish coalescing(空位操作符)。??运算符被称为空位操作符。如果第一个参数不是false,则返回第一个参数,否则返回第二个参数。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_39_1.jpg?sign=1739373196-w5eYHBxUCHtJJ7tG8278DXUxhNlnIF6M-0-db46b5b508ca3742daa280f79aff9210)
(6)globalThis。globalThis可获取不同环境的this,在ES2020规范之前,可以封装一层。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_39_2.jpg?sign=1739373196-0ZXZU3eILrnIHl9Y8Umz8mL7ycXgT2ey-0-5a783f92bc5761346e5cb4c3bbe78d39)
现在就可以按照如下方式使用了。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_39_3.jpg?sign=1739373196-rn6JgB8FR2P6ovpOHVayf1aRcRuY7L5z-0-13f7368cba7d7690a0f1d365e8898e13)
(7)模块命名空间导出(module namespace export)。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_39_4.jpg?sign=1739373196-j8bAtvsKvtyf1mREAF5HgGwJnNK2REfV-0-980f19319210686e69ef408b72be8e33)
(8)Promise.allSettled。Promise.allSettled接受一组promise,返回新的promise实例,并且所有这些参数实例都会返回结果,不管fulfilled状态还是rejected状态。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_39_5.jpg?sign=1739373196-c4jpwgojGchaE9NIjPWNkITAYaMbXSKY-0-ee6364af7dc2e7e33b07897533f4a1a1)
1.3.3 ES2019规范
(1)Array.flat Array.flatMap:如果数组的成员还是数组,则flat方法可以将嵌套的数组“拉平”,变成一维数组。该方法返回一个新数组,对原始数据没有影响。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_40_1.jpg?sign=1739373196-FtFPAJmm3vEdzxiDUWdgXA9s2XmwOnh3-0-9c5ca83015e872d5e074facfcc217020)
flatMap()只能展开一维数组。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_40_2.jpg?sign=1739373196-a6B1TqVGeICM4AOj5yYSBpkOZmY92KLs-0-fc528edae669c4ff2b82b706c21f3922)
(2)Object.fromEntries:将键值对数组转为对象。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_40_3.jpg?sign=1739373196-GJsnIvN0QUr5HNAo9VldjxWV2Yarepe9-0-d3c67f0b523ac06623134ff18230fcb9)
(3)String.trimStart和String.trimEnd:trimStart可去掉字符串头部的空格,trimEnd可去掉字符串尾部的空格。它们都返回新字符串,不影响原始字符串。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_40_4.jpg?sign=1739373196-MEbTP8OHNWVZVSyVBiDI6HElAzU0RjSo-0-d99faee29609ff7ee2e982878b376a17)
Arrary.sort:稳定排序。在ES2019中规定,排序必须稳定。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_40_5.jpg?sign=1739373196-vJa9iYNZdBIOxOnOERMM3sWtOKCdIh8R-0-932d0418cf1eb8a9b208db1d2b19e80f)
(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=1739373196-j3Y0HhXSEo8VQ6oeaDKatM3m5etXQMwV-0-862b9612224abe2b1d49a22459eb73a4)
1.3.4 ES2018规范
(1)对象的Rest/Spread:ES6为数组引入了扩展运算符的功能。在ES6中,只有数组有这个特性,从ES2018开始,对象也开始支持这个特性。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_41_2.jpg?sign=1739373196-4xmCeyWCf9Q1kHFMw2KxeNGaihRMCp80-0-e90341c255e2c80140352442e3ca859f)
(2)Promise.finally:该方法用于挃定不管promise对象的最后状态如何,都会执行的操作。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_41_3.jpg?sign=1739373196-vSDoYccGlQbuwSz2kWFRLktW6KXFqGo1-0-a6ff7aeae7f0674731c13ce5f6f0e08e)
(3)异步迭代器:循环遍历异步可迭代对象及同步可迭代对象,包括内置的String、Array,以及类似数组对象(例如arguments或NodeList、TypedArray、Map、Set)和用户定义的异步或同步迭代器。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_41_4.jpg?sign=1739373196-lM3gh3jjCw9ZL6JLDrnSMbox1lGJqFUT-0-b63a2b76e6d4760f7c5d8aaa6ad05baf)
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_42_1.jpg?sign=1739373196-efbIw2Gp8w8Q0oYhtgsjkenDREoMTTkL-0-2cf58566b74cccb78217d9d3eda3f5df)
正则表达式。ES2018引入s修饰符(dotAll模式),使.可以匹配任意单个字符。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_42_2.jpg?sign=1739373196-6LQFVr2o0FgsuuYb8aOSKwBQCx7gAl4J-0-cfd18bf66d28e0d26e21e57287f60abc)
ES2018为正则表达式引入了具名组匹配(Named Capture Groups),为每一组匹配挃定一个名称,既便于阅读代码,又便于引用。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_42_3.jpg?sign=1739373196-qbCTyyYeaR2CnHOuWpyedAEY432lc3TC-0-9ee1a7e128e16abd2a709ab4ff546776)
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=1739373196-klUkjb8L9hX85KwHJL7LKUqfLO1EDuRS-0-aaacb3c86691604226078a87fd983501)
Object.entries方法返回一个数组,返回对象自身的(不包括继承的)所有可遍历(enumerable)属性的键值对数组,该方法也适用于数组。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_42_5.jpg?sign=1739373196-4hnhkwoxjNsbPAiJBPVqPyh4ySo4XCTj-0-1b2d1a61f819bb5201fe6ff3bf3d6a86)
(2)字符串补全。padStart(targetLength [,padString)用于头部补全,padEnd(targetLength [,padString)用于尾部补全。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_43_1.jpg?sign=1739373196-lC2St100gzvixWj7f1RP2BrFBANmEjWG-0-bb5cd87805a5c126cd28bbe091adfa84)
(3)异步函数(asnyc)。异步函数是promise和generators(生成器)的组合,简化了promise的调用,提高了代码的可读性:
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_43_2.jpg?sign=1739373196-Vj9GFW90LsiV37b3Bwr1lEShT6Slao1K-0-3819806c15855b195d0e19df7c52af20)
(4)Object.getOwnPropertyDescriptors。该方法返回对象的自身属性,不包括继承的。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_43_3.jpg?sign=1739373196-oF7P3AaVKvTsiwku8jnviSAxt5Ch7YKj-0-ed3f06ce4ede9535e7fe9ecbe6af0a1e)