一、使用 # 号快速创建类的私有变量

类的主要目的之一是把我们的代码复用到更多模块中去,但是我们又不希望把所有的属性和方法都暴露出来,现在,有了这个新特性,我们就可以很轻易的实现这个想法了,只需要在我们的私有属性或者方法前面加一个 # 号即可:

class Message {
#message = "Howdy"

greet() { console.log(this.#message) }
}

const greeting = new Message()

greeting.greet() // Howdy
console.log(greeting.#message) // Private name #message is not defined

二、Promise.allSelected

当我们在使用多个 promise,尤其是这些 promise 有依赖关系时,打印每个 promise 的日志显得尤为重要,这可以帮助我们调试错误。有了 Promise.allSelected,我们可以创建一个新的 promise,这个 promise 会在包含的所有 promise 都执行完之后才返回,这将使我们能够访问一个数组,其中包含每个 promise 的返回值

const p1 = new Promise((res, rej) => setTimeout(res, 1000));

const p2 = new Promise((res, rej) => setTimeout(rej, 1000));

Promise.allSettled([p1, p2]).then(data => console.log(data));

// [
// Object { status: "fulfilled", value: undefined},
// Object { status: "rejected", reason: undefined}
// ]

三、空值合并运算符 ??

由于 JavaScript 的类型时动态的,在分配变量时,我们不得不去记住哪些值会被判断为真,哪些会被判断为假。当我们在创建一个对象时,通常会初始化属性为假的值,比如一个空字符串 或者是 0。设置默认值就会变得很烦人,因为它会覆盖有效值,看下如下 demo,你就会发现这么处理真的很烦人:

let person = {
profile: {
name: "",
age: 0
}
};

console.log(person.profile.name || "Anonymous"); // Anonymous
console.log(person.profile.age || 18); // 18

上述例子中,可能结果并不是我们想要的,我们想名字为空或者 0 岁也是合理的,应该不被代替,我们可以用 ?? 运算符替换掉 || 运算符,因为 ?? 运算符的类型检测会更严格一点,它只会把 null 和 undefined 判断为 false。

console.log(person.profile.name ?? "Anonymous"); // ""
console.log(person.profile.age ?? 18); // 0

四、可选链运算符

与空值合并运算符类似,JavaScript 在处理虚假值时,可能无法按照我们的意愿进行操作。当属性值未定义时,我们可以返回一个默认值,但是如果属性的路径未被定义呢?

答案是,可以通过在点符号前添加问号,我们可以将属性路径的任何部分设置为可选,以便操作。

let person = {};

console.log(person.profile.name ?? "Anonymous"); // person.profile is undefined
console.log(person?.profile?.name ?? "Anonymous"); // Anonymous
console.log(person?.profile?.age ?? 18); // 18

五、BigInt

通常,我们不会深入技术细节,但是由于 JavaScript 处理数字的方式,当你把研究的更加深入时,事情就会变得有点不靠谱。 Javascript 可以处理的最大数字是2 ^ 53,我们可以用 MAX safe integer 看到。

const max = Number.MAX_SAFE_INTEGER;

console.log(max); // 9007199254740991

如果超过这个数字,就会变得有点奇怪

console.log(max + 1); // 9007199254740992
console.log(max + 2); // 9007199254740992
console.log(max + 3); // 9007199254740994
console.log(Math.pow(2, 53) == Math.pow(2, 53) + 1); // true

我们可以使用新的数据类型 BigInt 来处理上述问题。只需在数字后面加个符号 n,我们就可以疯狂的使用大的数值了。我们不能用 BigInt 数字混淆标准数字,所以一般在数学计算时使用 BigInt 类型。

const bigNum = 100000000000000000000000000000n;

console.log(bigNum * 2n); // 200000000000000000000000000000n

六、使用 async/await 动态导入模块

如果我们有很多的功能函数,有些是很少用的,那么一起导入会使资源浪费,现在我们可以使用 async/await 来动态导入这些依赖了,但是这个方法仅适用于 node.js 环境。

// math.js
const add = (num1, num2) => num1 + num2;

export { add };
const doMath = async (num1, num2) => {
if (num1 && num2) {
const math = await import('./math.js');
console.log(math.add(5, 10));
};
};

doMath(4, 2);

翻译自:https://alligator.io/js/es2020/