0%

ES2021(ES12)

js又双叒叕更新了!这一版的新功能看上去真不戳,总共详细介绍了5 个新特性,replaceAll()真方便,可以不要每次都利用正则表达式里的g后缀来做替换了,剑指的替换空格又有了新的替换方法,赞美一下。Chrome浏览器已经支持了,力扣用过了也能顺利通过,剑指 Offer 05. 替换空格

请实现一个函数,把字符串 s 中的每个空格替换成”%20”。

示例 1:

1
2
输入:s = "We are happy."
输出:"We%20are%20happy."

限制:

1
0 <= s 的长度 <= 10000

采用replaceAll

1
2
3
4
5
6
7
8
/**
* @param {string} s
* @return {string}
* 库函数
*/
var replaceSpace = function(s) {
return s.replaceAll(' ', '%20');
};

1.String.prototype.replaceAll()

在 JavaScript 中,通常会使用 String.prototype.replace() 方法来完成字符串的替换,例如:

1
2
'aaaa'.replace('a', 'b');
// baaa

String.prototype.replace() 方法中,当第一个参数是字符串类型时,只替换第一个匹配的字符串,相关细节可以参阅 MDN 文档。因此,在上面的代码中,只有第一个 a 被替换成了 b,第二个 a 保持不变。如果要将匹配的字符串全部替换,传统方法只能通过正则表达式实现,例如:

1
2
'aaaa'.replace(/a/g, 'b');
// bbbb

为了方便字符串的全局替换,ES2021 将支持 String.prototype.replaceAll() 方法,可以不用写正则表达式就可以完成字符串的全局替换,例如:

1
2
'aaaa'.replaceAll('a', 'b');
// bbbb

更多阅读

2.Promise.any

ES6引入Promise ,当时支持Promise.allPromise.race2种方法:

  • Promise.all: 只要有一个 promise 是 rejected,则立即返回一个 rejected promise;所有的 promise 都是 fulfilled 时,则返回一个 resolved promise
1
2
3
4
5
6
7
8
Promise.all([
Promise.reject(1),
Promise.resolve(2)
])
.then(result => console.log('result:', result))
.catch(error => console.error('error:', error));

// error: 1
  • Promise.race: 只要有 promise 是 fulfilled 或 rejected,则立即返回一个 resolved 或 rejected的promise
1
2
3
4
5
6
7
8
Promise.race([
Promise.reject(1),
Promise.resolve(2)
])
.then(result => console.log('result:', result))
.catch(error => console.error('error:', error));

// error: 1

ES2020(ES11)引入了Promise.allSettled方法

  • Promise.allSettled: 无论每一个 promise 是fulfilled 还是 rejected,返回值都是一个 resolved promise
1
2
3
4
5
6
7
8
9
10
Promise.allSettled([
Promise.reject(1),
Promise.resolve(2)
])
.then(result => console.log('result:', result))
.catch(error => console.error('error:', error));

// result:
// [{ status: "rejected", reason: 1 },
// { status: "fulfilled", value: 2 }]

最新的ES2021(ES12)引入了Promise.any方法

  • Promise.any: 只要有一个 promise 是 fulfilled 时,则返回一个 resolved promise;所有的 promise 都是 rejected 时,则返回一个 rejected promise
1
2
3
4
5
6
7
8
Promise.any([
Promise.reject(1),
Promise.resolve(2)
])
.then(result => console.log('result:', result))
.catch(error => console.error('error:', error));

// result: 2

更多阅读

3.逻辑赋值运算符

逻辑赋值运算符由逻辑运算符和赋值表达式组合而成:

  • or or equals (||=)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    a ||= b;

    // 与 a ||= b 等价
    a || (a = b);

    // 与 a ||= b 等价
    if (!a) {
    a = b;
    }
  • and and equals (&&=)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    a &&= b;

    // 与 a &&= b 等价
    a && (a = b);

    // 与 a &&= b 等价
    if (a) {
    a = b;
    }
  • question question equals (??=)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    a ??= b;

    // 与 a ??= b 等价
    a ?? (a = b);

    // 与 a ??= b 等价
    if (a === null || a === undefined) {
    a = b;
    }

用法示例:

1
2
3
4
5
6
7
8
9
10
let obj = {};

obj.x ??= 0;
console.log(obj.x) // 0

obj.x ||= 1;
console.log(obj.x) // 1

obj.x &&= 2;
console.log(obj.x) // 2

注意事项:

1
2
3
a = a || b; // 与 a ||= b 不等价
a = a && b; // 与 a &&= b 不等价
a = a ?? b; // 与 a ??= b 不等价

不等价的原因在于,无论上面的每个逻辑表达式结果如何,都会进行赋值运算;而逻辑赋值运算符只会在条件成立的情况下进行赋值,比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
let x = 0;
const obj = {
get x() {
return x;
},

set x(value) {
console.log('setter called');
x = value;
}
};

// This always logs "setter called"
obj.x += 1;
assert.equal(obj.x, 1);

// Logical operators do not call setters unnecessarily
// This will not log.
obj.x ||= 2;
assert.equal(obj.x, 1);

// But setters are called if the operator does not short circuit
// "setter called"
obj.x &&= 3;
assert.equal(obj.x, 3);

更多阅读

4.数字分隔符

使用 _ 对数字进行分割,提高数字的可读性,例如在日常生活中数字通常是每三位数字之间会用 , 分割,以方便人快速识别数字。在代码中,也需要程序员较便捷的对数字进行辨识:

1
2
3
4
5
6
7
// 1000000000 不易辨识
const count1 = 1000000000;

// 1_000_000_000 很直观
const count2 = 1_000_000_000;

console.log(count1 === count2); // true

更多案例

1
2
3
4
5
6
const goldstack1 = 785_00;
const gemstack = 1_000_000_000;
console.log(goldstack1); // 78500
console.log(gemstack); // 1000000000
console.log(goldstack1 === 78500); // true
console.log(gemstack === 1000000000); // true

我们通过在数字相符的组之间放置分隔符使数字值更加的可读,分隔符适用于十进制表示法的数字以及二进制或十六进制表示法的数字,以及ES2020中引入的BigInt。

1
2
3
4
5
6
7
8
9
10
11
const goldStack = 0b1111_1111_1110_0101;
console.log(goldStack); // 65509
console.log(goldStack === 0b1111111111100101); // true

const goldStack = 0xFF_AC_C1;
console.log(goldStack); // 16755905
console.log(goldStack === 0xFF_AC_C1); // true

const goldtstack = 1_000_000_000_000_000n;
console.log(goldtstack); // 1000000000000000n
console.log(goldtstack === BigInt(10 ** 15)); // true

注意: 分隔符不会影响===操作符比较两个值

5.WeakRefs

ES6实现了WeakSetWeakMapWeakSet是对象的集合,WeakMap是键值对的集合,键必须是一个对象。它们之间的联系属于弱引用,也就是说这些对象作为垃圾回收的一部分,如果没有其他强引用,可以从内存中被移除。一个对象的弱引用是不会阻止垃圾回收器移除内存中的这个对象。相反,一个普通(强)引用的对象会保留这个对象在内存中。

ES2021将可以实现人为使用WeakRef对象而不用WeakSetWeakMap来创建一个对象的若引用。这个符合需要的提案警告你在使用WeakRef时一定要小心。总之,使用之前一定有合理理由。根本上来说,我们应该尽可能的避免使用WeakRef。垃圾回收器已经够复杂和系统依赖的,所以这很难去预测垃圾回收器的具体行为。

WeakRef 实例可以作为对象的弱引用,对象的弱引用是指当该对象应该被 GC 回收时不会阻止 GC 的回收行为。而与此相反的,一个普通的引用(默认是强引用)会将与之对应的对象保存在内存中。只有当该对象没有任何的强引用时,JavaScript 引擎 GC 才会销毁该对象并且回收该对象所占的内存空间。因此,访问弱引用指向的对象时,很有可能会出现该对象已经被回收,WeakRef 使用方法如下:

1
2
3
4
5
6
const ref = new WeakRef({ name: 'koofe' });
console.log(ref.name); // undefined
let obj = ref.deref();
if (obj) {
console.log(obj.name); // koofe
}

对于 WeakRef 对象的使用要慎重考虑,能不使用就尽量不要使用

更多阅读

-------------本文结束感谢您的阅读-------------

欢迎关注我的其它发布渠道