3. Object.fromEntries()
Object.fromEntries()方法可以把键值对列表转换为一个对象。该方法相当于 Object.entries() 方法的逆过程。 Object.entries()方法返回一个给定对象自身可枚举属性的键值对数组,而Object.fromEntries() 方法把键值对列表转换为一个对象。
const object = { key1: 'value1', key2: 'value2' } const array = Object.entries(object) // [ ["key1", "value1"], ["key2", "value2"] ] Object.fromEntries(array) // { key1: 'value1', key2: 'value2' } 复制代码
使用该方法主要有以下两个用途:
(1)将数组转成对象
const entries = [ ['foo', 'bar'], ['baz', 42] ] Object.fromEntries(entries) // { foo: "bar", baz: 42 } 复制代码
(2)将 Map 转成对象
const entries = new Map([ ['foo', 'bar'], ['baz', 42] ]) Object.fromEntries(entries) // { foo: "bar", baz: 42 } 复制代码
4. Symbol描述
通过 Symbol() 创建符号时,可以通过参数提供字符串作为描述:
let dog = Symbol("dog"); // dog 为描述 复制代码
在 ES2019 之前,获取一个 Symbol 值的描述需要通过 String 方法 或 toString 方法:
String(dog); // "Symbol(dog)" dog.toString(); // "Symbol(dog)" 复制代码
ES2019 补充了属性 description,用来直接访问描述:
dog.description; // dog 复制代码
5. toString()
ES2019 对函数的 toString() 方法进行了扩展,以前这个方法只会输出函数代码,但会省略注释和空格。ES2019 的 toString()则会保留注释、空格等,即输出的是原始代码:
function sayHi() { /* dog */ console.log('wangwang'); } sayHi.toString(); // 将输出和上面一样的原始代码 复制代码
6. catch
在 ES2019 以前,catch 会带有参数,但是很多时候 catch 块是多余的。而现在可以不带参数:
// ES2019 之前 try { ... } catch(error) { ... } // ES2019 之后 try { ... } catch { ... } 复制代码
六、ES11 新特性(2020)
1. BigInt
在 JavaScript 中,数值类型 Number 是 64 位浮点数**,所以计算精度和表示范围都有一定限制。ES2020 新增了 BigInt 数据类型,这也是 JavaScript 引入的**第八种基本类型。BigInt 可以表示任意大的整数。其语法如下:
BigInt(value); 复制代码
其中 value 是创建对象的数值。可以是字符串或者整数。
在 JavaScript 中,Number 基本类型可以精确表示的最大整数是253。因此早期会有这样的问题:
let max = Number.MAX_SAFE_INTEGER; // 最大安全整数 let max1 = max + 1 let max2 = max + 2 max1 === max2 // true 复制代码
有了BigInt之后,这个问题就不复存在了:
let max = BigInt(Number.MAX_SAFE_INTEGER); let max1 = max + 1n let max2 = max + 2n max1 === max2 // false 复制代码
可以通过typeof操作符来判断变量是否为BigInt类型(返回字符串"bigint"):
typeof 1n === 'bigint'; // true typeof BigInt('1') === 'bigint'; // true 复制代码
还可以通过Object.prototype.toString
方法来判断变量是否为BigInt类型(返回字符串"[object BigInt]"):
Object.prototype.toString.call(10n) === '[object BigInt]'; // true 复制代码
注意,BigInt 和 Number 不是严格相等的,但是宽松相等:
10n === 10 // false 10n == 10 // true 复制代码
Number 和 BigInt 可以进行比较:
1n < 2; // true 2n > 1; // true 2 > 2; // false 2n > 2; // false 2n >= 2; // true 复制代码
2. 空值合并运算符(??)
在编写代码时,如果某个属性不为 null 和 undefined,那么就获取该属性,如果该属性为 null 或 undefined,则取一个默认值:
const name = dogName ? dogName : 'default'; 复制代码
可以通过 || 来简化:
const name = dogName || 'default'; 复制代码
但是 || 的写法存在一定的缺陷,当 dogName 为 0 或 false 的时候也会走到 default 的逻辑。所以 ES2020 引入了 ?? 运算符。只有 ?? 左边为 null 或 undefined时才返回右边的值:
const dogName = false; const name = dogName ?? 'default'; // name = false; 复制代码
3. 可选链操作符(?.)
在开发过程中,我们经常需要获取深层次属性,例如 system.user.addr.province.name。但在获取 name 这个属性前需要一步步的判断前面的属性是否存在,否则并会报错:
const name = (system && system.user && system.user.addr && system.user.addr.province && system.user.addr.province.name) || 'default'; 复制代码
为了简化上述过程,ES2020 引入了「链判断运算符」?.,可选链操作符( ?. )允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。?. 操作符的功能类似于 . 链式操作符,不同之处在于,在引用为null 或 undefined 的情况下不会引起错误,该表达式短路返回值是 undefined。与函数调用一起使用时,如果给定的函数不存在,则返回 undefined。
const name = system?.user?.addr?.province?.name || 'default'; 复制代码
当尝试访问可能不存在的对象属性时,可选链操作符将会使表达式更短、更简明。在探索一个对象的内容时,如果不能确定哪些属性必定存在,可选链操作符也是很有帮助的。
可选链有以下三种形式:
a?.[x] // 等同于 a == null ? undefined : a[x] a?.b() // 等同于 a == null ? undefined : a.b() a?.() // 等同于 a == null ? undefined : a() 复制代码
在使用TypeScript开发时,这个操作符可以解决很多问题。
七、ES12 新特性(2021)
1. String.prototype.replaceAll()
replaceAll()方法会返回一个全新的字符串,所有符合匹配规则的字符都将被替换掉,替换规则可以是字符串或者正则表达式。
let string = 'hello world, hello ES12' string.replace(/hello/g,'hi') // hi world, hi ES12 string.replaceAll('hello','hi') // hi world, hi ES12 复制代码
注意的是,replaceAll 在使用正则表达式的时候,如果非全局匹配(/g),会抛出异常:
let string = 'hello world, hello ES12' string.replaceAll(/hello/,'hi') // Uncaught TypeError: String.prototype.replaceAll called with a non-global 复制代码
2. 数字分隔符
数字分隔符可以在数字之间创建可视化分隔符,通过 _ 下划线来分割数字,使数字更具可读性,可以放在数字内的任何地方:
const money = 1_000_000_000 //等价于 const money = 1000000000 复制代码
该新特性同样支持在八进制数中使用:
const number = 0o123_456 //等价于 const number = 0o123456 复制代码
3. Promise.any
Promise.any是是 ES2021 新增的特性,它接收一个 Promise 可迭代对象(例如数组),只要其中的一个 promise 成功,就返回那个已经成功的 promise 如果可迭代对象中没有一个 promise 成功(即所有的 promises 都失败/拒绝),就返回一个失败的 promise 和 AggregateError 类型的实例,它是 Error 的一个子类,用于把单一的错误集合在一起
const promises = [ Promise.reject('ERROR A'), Promise.reject('ERROR B'), Promise.resolve('result'), ] Promise.any(promises).then((value) => { console.log('value: ', value) }).catch((err) => { console.log('err: ', err) }) // 输出结果:value: result 复制代码
如果所有传入的 promises 都失败:
const promises = [ Promise.reject('ERROR A'), Promise.reject('ERROR B'), Promise.reject('ERROR C'), ] Promise.any(promises).then((value) => { console.log('value:', value) }).catch((err) => { console.log('err:', err) console.log(err.message) console.log(err.name) console.log(err.errors) }) 复制代码
输出结果:
err:AggregateError: All promises were rejected All promises were rejected AggregateError ["ERROR A", "ERROR B", "ERROR C"]