![前端开发必知必会:从工程核心到前沿实战](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=1738847458-c7s9HYKuBuAWE4MqOQnR75LvAmzny9ov-0-d040d128f51be728fc73081873908d9a)
上面的代码可以将所有的b替换成下画线,如果不加正则表达式,则只替换第一个字符。下面使用replaceAll实现相同的功能:
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_34_2.jpg?sign=1738847458-u6kbwPbM8nfHjGed0yHfmauBmiRkSKfn-0-ab402264c57aa3fbbaf259fc43db8f5b)
使用新API后,好处有两点:代码的可读性更好,特殊符号不需要再转义。
(2)逻辑赋值运算符。逻辑赋值运算符结合了逻辑运算符和赋值表达式。逻辑赋值运算符有三种:||=、&&=和??=,如表1-1所示。
表1-1
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_34_3.jpg?sign=1738847458-OMoT9CzSt6UqopRMKuEsA7pU8s3mJafh-0-391b11307a213402aaa9b004fcac32d0)
逻辑赋值运算符同样遵守逻辑短路(Short-circuiting)。当将逻辑操作与赋值组合起来时,因为赋值可能会导致副作用,所以赋值操作应该是在某种条件下才进行的。因为副作用会对程序的性能甚至正确性产生负面影响。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_34_4.jpg?sign=1738847458-l4TObFJmc7T3iLcsH3cyb4mJ6yl7d3oO-0-82a03b81b5fdde27bb65e138838199ff)
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_35_1.jpg?sign=1738847458-lEQ3RkYtw4Gl3vot7SMjAU6eSWjweeM1-0-14f0b9a34bf8a36aa0f3d746abf700e7)
(3)WeakRef。通常来说,对JavaScript对象的引用都是强引用。也就是说,一旦保持对某个对象的引用,这个对象就不会被垃圾回收。但是在ES6中引入了WeakMap和WeakSet,这两者中的对象都是弱引用,垃圾回收机制不考虑WeakSet和WeakMap对集合中对象的引用,只要这些对象不再被引用,垃圾回收机制就会自动回收该对象的内存,不考虑该对象是否还存在于Weak集合中。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_35_2.jpg?sign=1738847458-N31eF1juF4aoUuLKAMlq5UrOroQ5CxMT-0-393e3d1b6dcdcb3e08e1683865d17d91)
此时,在该代码块中不再保持对对象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=1738847458-t93Ms8SavWWUNnFPDXKvwrgfDl4qIly2-0-2739eb35e716fb622777134262e216d0)
FinalizationRegistry接收一个注册器回调函数,可以利用该注册器为挃定对象注册一个事件监听器。在对象被垃圾回收之后,会触发监听的事件。首先,创建一个注册器:
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_36_1.jpg?sign=1738847458-fB26NGWJ2ngFyQDUvA8SBlV0k4JjjTwi-0-5be03d272817f16301064478a2cd63f8)
接着,注册一个挃定对象,同时挃定给注册器回调传递的参数。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_36_2.jpg?sign=1738847458-uuPJA8i7tFg4IO27LQZ9CznhGOrrGlhb-0-d308287dc5416386e14cdb21c0a6b122)
(4)数字分隑符。数字分隑符提供了一种使大数字更易于阅读和使用的简单方法:
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_36_3.jpg?sign=1738847458-6OyYA5ZaOWotpW8jVZcsWmndFnofFX63-0-ebfd83b7dc457de6ac7d7e8faab4090a)
(5)Promise.any。接收几个promise对象,只要其中任意一个成功,就返回那个成功的promise对象。如果所有的promise对象都失败,就返回一个失败的promise对象。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_36_4.jpg?sign=1738847458-MJBrWoKy0qGcvh36APbd3Z2vZWE6a3Fc-0-f1a3262035aa6bc2c38efdc447c8737d)
下面对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=1738847458-APQTOZZmxrYOxsKxBY1nOX7GINqY7FoY-0-98bbc172980559c425f04794d40b7c70)
返回结果如下。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_37_2.jpg?sign=1738847458-xRn76xKHjrEYaMfUzSXlkT1p4iZynXbV-0-b5bd8d95a662aa2bfefd1d5bf8937ca8)
(2)动态导入(dynamic import)。动态导入提供了一种类似函数的新的导入形式,与静态导入相比,有更多的新功能。
先看一下静态导入。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_37_3.jpg?sign=1738847458-CjJnKQgdR0mJUfZeMvTUfCkeyAflKhoM-0-178a88923d033010ac81631501421359)
接下来就可以在script中导入了。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_37_4.jpg?sign=1738847458-97K2xMCDAEPTDge5npYMbIcit5PVrW0Z-0-a38ffde3476c2376e4ae05c804bdf3b6)
这种导入模块的语法形式是一个静态声明:它仅接受字符串文字作为模块标识,通过运行前的“链接”过程,引入绑定(bindings)到本地作用域中。静态导入只能在文件的顶层使用。
import(specifier)函数支持动态加载模块。Import函数的参数specifier可以挃定所要加载的模块的位置,并返回promise对象:
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_38_1.jpg?sign=1738847458-L8oWB4iQiAfhZu4ZJFhU8Ce7bAWqoBAD-0-2fcda34dd06c27920c1cac4d97c75d96)
(3)BigInt。它提供了一种表示大于253-1的整数的方法,也就是说,可以表示任意大的整数。具体用法是通过在一个整数字面量后面加n的方式定义一个BigInt类型:
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_38_2.jpg?sign=1738847458-L3cE588OH3xHR2nRSIfhpzsCEI1fzgdh-0-a8c9872ad320ab400b8a26acb46b5da7)
(4)Optional Chaining(可选链操作符)。?.运算符被称为链刞断运算符,它允许开发人员读取深度嵌套在对象链中的属性值,而不必验证每个属性是否都存在。当引用为空时,返回undefined。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_38_3.jpg?sign=1738847458-3AtbnfsrGClCmGcTlZKAG3H8Pgi8rbuW-0-7d42a22623a572f4fb200c33e76ce270)
(5)Nullish coalescing(空位操作符)。??运算符被称为空位操作符。如果第一个参数不是false,则返回第一个参数,否则返回第二个参数。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_39_1.jpg?sign=1738847458-ZJHyUJdTfEj6mP5a14Ln8Nhk2E3Agqah-0-5bce8797b89f689720638255f8d43285)
(6)globalThis。globalThis可获取不同环境的this,在ES2020规范之前,可以封装一层。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_39_2.jpg?sign=1738847458-HNQgIZ5HyEsXpJDb81zdIeAdC3XEdr00-0-780b6e74892b8b5cba070ebc978804e0)
现在就可以按照如下方式使用了。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_39_3.jpg?sign=1738847458-lfpVg8wkzZFeiN9afVX7j0PKqcoRzPvT-0-8c40873ef735c24979124fd814e190aa)
(7)模块命名空间导出(module namespace export)。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_39_4.jpg?sign=1738847458-yg4feDG9fal390R0Rqm57XhHXMBBiHtK-0-74052211003f9f26936b096a8a840a9d)
(8)Promise.allSettled。Promise.allSettled接受一组promise,返回新的promise实例,并且所有这些参数实例都会返回结果,不管fulfilled状态还是rejected状态。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_39_5.jpg?sign=1738847458-YBCirHwIYvvQbijBXxSOYLpboOXl8qQZ-0-cd3ab4b6d9a788f20f62457c3c845306)
1.3.3 ES2019规范
(1)Array.flat Array.flatMap:如果数组的成员还是数组,则flat方法可以将嵌套的数组“拉平”,变成一维数组。该方法返回一个新数组,对原始数据没有影响。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_40_1.jpg?sign=1738847458-OR4AWKOXxvFlEMS6TZrlxGuCoz5RKKBl-0-dd87d69d7ce38608b487bf88637b4e08)
flatMap()只能展开一维数组。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_40_2.jpg?sign=1738847458-F20eTrUEGD8ALRCqPuhVDhm2lSWFKLhV-0-4bc6101b3b7bbc1c5beac9a93ccfa2bc)
(2)Object.fromEntries:将键值对数组转为对象。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_40_3.jpg?sign=1738847458-uoH3jnL0RPuCaiw872AbIg9XDHZSefMG-0-f0fc037d999ab640578c7919117cdbff)
(3)String.trimStart和String.trimEnd:trimStart可去掉字符串头部的空格,trimEnd可去掉字符串尾部的空格。它们都返回新字符串,不影响原始字符串。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_40_4.jpg?sign=1738847458-qjFB8vqfCPSCRzlTy9lNd4rclOO79BMg-0-e1fb83e57be1255e4540e49bce4e139c)
Arrary.sort:稳定排序。在ES2019中规定,排序必须稳定。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_40_5.jpg?sign=1738847458-VDivmlNWUsWvJPnN6SvFZrF4kfKqBrP7-0-1b88af128e62f3b0c19069b965b6b9c0)
(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=1738847458-K5tnxJedYeIkUc8gub2C0aQjTOeBvVPi-0-3247cd86f443a36798d35f7c9142d96b)
1.3.4 ES2018规范
(1)对象的Rest/Spread:ES6为数组引入了扩展运算符的功能。在ES6中,只有数组有这个特性,从ES2018开始,对象也开始支持这个特性。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_41_2.jpg?sign=1738847458-0Bl1gc3SBONFcOCuWCzmgWPSj4wRfZXn-0-058f1cfbc81d722adf61db4d9e922983)
(2)Promise.finally:该方法用于挃定不管promise对象的最后状态如何,都会执行的操作。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_41_3.jpg?sign=1738847458-Npmf4ha68gw5KwX4TwFrYYvBxRJNQ8nf-0-8a17ece9be089400b1bedac907a9637d)
(3)异步迭代器:循环遍历异步可迭代对象及同步可迭代对象,包括内置的String、Array,以及类似数组对象(例如arguments或NodeList、TypedArray、Map、Set)和用户定义的异步或同步迭代器。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_41_4.jpg?sign=1738847458-fnnGS3K2E7sGyaqZPjBVd6PgqQEd3EMV-0-b9e6eee8883eb14f14ff707dfbad248e)
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_42_1.jpg?sign=1738847458-UmLRQ3SGP7zlMKYxdulc9VxKvHVlVaWt-0-df5b3b5c6b9a0afbe95c859e3eed5c2f)
正则表达式。ES2018引入s修饰符(dotAll模式),使.可以匹配任意单个字符。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_42_2.jpg?sign=1738847458-yCFi0QX6NjPc56vpXhFSIUty8aMkXpQc-0-872d9ade9a6a4175460b044caf0dbb26)
ES2018为正则表达式引入了具名组匹配(Named Capture Groups),为每一组匹配挃定一个名称,既便于阅读代码,又便于引用。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_42_3.jpg?sign=1738847458-OUHwjsyw9WZjRA3iGjXIQnlnzEOmx5zI-0-bb358fa5d9b777f65293304c54a0d608)
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=1738847458-7MndX5fl6EFdOa9UI63H8dJpvlXUEJ7a-0-e6aa12603d3ef1207d88c2ae03cd2f2e)
Object.entries方法返回一个数组,返回对象自身的(不包括继承的)所有可遍历(enumerable)属性的键值对数组,该方法也适用于数组。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_42_5.jpg?sign=1738847458-w8iDUelfqc9mJpVj4QMRrzhp5Eys6Nu3-0-c9986d465f3fcb664d1ed3b6ef0e2582)
(2)字符串补全。padStart(targetLength [,padString)用于头部补全,padEnd(targetLength [,padString)用于尾部补全。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_43_1.jpg?sign=1738847458-F5i0fuCLntHEEmM63MLAMSuVxG20Lokp-0-172440d2f3726434b9fd7e8bf0565896)
(3)异步函数(asnyc)。异步函数是promise和generators(生成器)的组合,简化了promise的调用,提高了代码的可读性:
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_43_2.jpg?sign=1738847458-fGMGKiBm9nSOMhL2Tlx1kbYsxXrwTUXu-0-6c62de0599171a1c1b2a9c69fcad623d)
(4)Object.getOwnPropertyDescriptors。该方法返回对象的自身属性,不包括继承的。
![](https://epubservercos.yuewen.com/7211F1/21440186701519806/epubprivate/OEBPS/Images/41800_43_3.jpg?sign=1738847458-PBP6M85fWJWohipNJ3ywk2eLFquXf42f-0-5a35601035a43dbcf29b0c7be3afc67e)