1.3 ES规范
截止到2021年3月9日,EcmaScript规范(简称ES规范)已经发布到2021版的候选版本,该版本包含了几个实用的特性。本节我们总结一下从ES2021到ES2017各个规范的新增特性,便于大家综合参考。
1.3.1 ES2021规范
(1)String.prototype.replaceAll:在replaceAll方法出现之前,字符串替换可以使用replace配合正则表达式的方式,看下面两个例子。
上面的代码可以将所有的b替换成下画线,如果不加正则表达式,则只替换第一个字符。下面使用replaceAll实现相同的功能:
使用新API后,好处有两点:代码的可读性更好,特殊符号不需要再转义。
(2)逻辑赋值运算符。逻辑赋值运算符结合了逻辑运算符和赋值表达式。逻辑赋值运算符有三种:||=、&&=和??=,如表1-1所示。
表1-1
逻辑赋值运算符同样遵守逻辑短路(Short-circuiting)。当将逻辑操作与赋值组合起来时,因为赋值可能会导致副作用,所以赋值操作应该是在某种条件下才进行的。因为副作用会对程序的性能甚至正确性产生负面影响。
(3)WeakRef。通常来说,对JavaScript对象的引用都是强引用。也就是说,一旦保持对某个对象的引用,这个对象就不会被垃圾回收。但是在ES6中引入了WeakMap和WeakSet,这两者中的对象都是弱引用,垃圾回收机制不考虑WeakSet和WeakMap对集合中对象的引用,只要这些对象不再被引用,垃圾回收机制就会自动回收该对象的内存,不考虑该对象是否还存在于Weak集合中。
此时,在该代码块中不再保持对对象ref的引用,垃圾回收机制随时可以对它进行回收。
WeakMap和WeakSet不是真正的弱引用,只要key是活动的,还是会保持强引用。一旦key被垃圾回收,则Weak集合仅弱引用其内容。
WeakRef是一个高级API,它提供了真正的弱引用,允许创建对象的弱引用,当跟踪现有对象时不会阷止对其进行垃圾回收,这对于缓存和对象映射非常有用。当浏览器需要进行垃圾回收时,如果对该对象的唯一引用来自WeakRef变量,则JavaScript引擎可以安全地从内存中初除该对象并释放空间。下面的代码是使用WeakRef构造方法构造的一个实例,然后通过实例的deref方法访问变量。
FinalizationRegistry接收一个注册器回调函数,可以利用该注册器为挃定对象注册一个事件监听器。在对象被垃圾回收之后,会触发监听的事件。首先,创建一个注册器:
接着,注册一个挃定对象,同时挃定给注册器回调传递的参数。
(4)数字分隑符。数字分隑符提供了一种使大数字更易于阅读和使用的简单方法:
(5)Promise.any。接收几个promise对象,只要其中任意一个成功,就返回那个成功的promise对象。如果所有的promise对象都失败,就返回一个失败的promise对象。
下面对Promise.all和Promise.race做一个简单对比。
Promise.all:只要有一个promise对象失败,就返回失败;只有所有的promise对象都成功,才返回成功。Promise.race:只要有一个promise对象状态发生改变,就返回该promise对象。
1.3.2 ES2020规范
(1)String.protype.matchAll。matchAll方法可返回一个正则表达式在字符串的所有匹配。下面先实现一个例子,即匹配十六进制的字符。
返回结果如下。
(2)动态导入(dynamic import)。动态导入提供了一种类似函数的新的导入形式,与静态导入相比,有更多的新功能。
先看一下静态导入。
接下来就可以在script中导入了。
这种导入模块的语法形式是一个静态声明:它仅接受字符串文字作为模块标识,通过运行前的“链接”过程,引入绑定(bindings)到本地作用域中。静态导入只能在文件的顶层使用。
import(specifier)函数支持动态加载模块。Import函数的参数specifier可以挃定所要加载的模块的位置,并返回promise对象:
(3)BigInt。它提供了一种表示大于253-1的整数的方法,也就是说,可以表示任意大的整数。具体用法是通过在一个整数字面量后面加n的方式定义一个BigInt类型:
(4)Optional Chaining(可选链操作符)。?.运算符被称为链刞断运算符,它允许开发人员读取深度嵌套在对象链中的属性值,而不必验证每个属性是否都存在。当引用为空时,返回undefined。
(5)Nullish coalescing(空位操作符)。??运算符被称为空位操作符。如果第一个参数不是false,则返回第一个参数,否则返回第二个参数。
(6)globalThis。globalThis可获取不同环境的this,在ES2020规范之前,可以封装一层。
现在就可以按照如下方式使用了。
(7)模块命名空间导出(module namespace export)。
(8)Promise.allSettled。Promise.allSettled接受一组promise,返回新的promise实例,并且所有这些参数实例都会返回结果,不管fulfilled状态还是rejected状态。
1.3.3 ES2019规范
(1)Array.flat Array.flatMap:如果数组的成员还是数组,则flat方法可以将嵌套的数组“拉平”,变成一维数组。该方法返回一个新数组,对原始数据没有影响。
flatMap()只能展开一维数组。
(2)Object.fromEntries:将键值对数组转为对象。
(3)String.trimStart和String.trimEnd:trimStart可去掉字符串头部的空格,trimEnd可去掉字符串尾部的空格。它们都返回新字符串,不影响原始字符串。
Arrary.sort:稳定排序。在ES2019中规定,排序必须稳定。
(4)JSON.stringfy改造:如果遇到0xD800到0xDFFF之间的单个码点,或者不存在的配对形式,则返回转义字符串。
(5)Symbol description属性:ES2019为Symbol提供了一个实例属性description,可以查看Symbol的描述。
1.3.4 ES2018规范
(1)对象的Rest/Spread:ES6为数组引入了扩展运算符的功能。在ES6中,只有数组有这个特性,从ES2018开始,对象也开始支持这个特性。
(2)Promise.finally:该方法用于挃定不管promise对象的最后状态如何,都会执行的操作。
(3)异步迭代器:循环遍历异步可迭代对象及同步可迭代对象,包括内置的String、Array,以及类似数组对象(例如arguments或NodeList、TypedArray、Map、Set)和用户定义的异步或同步迭代器。
正则表达式。ES2018引入s修饰符(dotAll模式),使.可以匹配任意单个字符。
ES2018为正则表达式引入了具名组匹配(Named Capture Groups),为每一组匹配挃定一个名称,既便于阅读代码,又便于引用。
1.3.5 ES2017规范
(1)Object.values/Object.entries。Object.values方法返回一个数组,返回对象自身的(不包括继承的)所有可遍历(enumerable)属性的值。
Object.entries方法返回一个数组,返回对象自身的(不包括继承的)所有可遍历(enumerable)属性的键值对数组,该方法也适用于数组。
(2)字符串补全。padStart(targetLength [,padString)用于头部补全,padEnd(targetLength [,padString)用于尾部补全。
(3)异步函数(asnyc)。异步函数是promise和generators(生成器)的组合,简化了promise的调用,提高了代码的可读性:
(4)Object.getOwnPropertyDescriptors。该方法返回对象的自身属性,不包括继承的。