1.通过 # 给 class 添加私有变量
class Counter {
#number = 10
increment() {
this.#number++
}
getNum() {
return this.#number
}
}
const counter = new Counter()
counter.increment()
console.log(counter.getNum()) //11
console.log(counter.#number) //SyntaxError
在 ES2020 中,通过 #
可以给 class 添加私有变量。在 class 的外部我们无法获取该值。当我们尝试输出 counter.#number
,语法错误被抛出:无法在 class Counter
外部获取它。这样就不需要使用闭包来隐藏不想暴露给外界的私有变量。BigInt
2.BigInt
Js 中 Number类型只能安全的表示-(2^53-1)至 2^53-1 范的值,超出这个范围的整数计算或者表示会丢失精度,我们可以用 BigInt 对象表示不在这个范围内的数。可以通过常规操作进行加、减、乘、除、余数和幂等运算。它可以由数字和十六进制或二进制字符串构造。此外它还支持 AND、OR、NOT 和 XOR 之类的按位运算。唯一无效的位运算是零填充右移运算符(>>>)。
使用BigInt 有两种方式:1.在整数字面量后面加n。2. BigInt 函数。
let a = 123n;
let b = BigInt(456n);
console.log(typeof a) //bigint
console.log(a+b) //579n
1n == 1 //true
1n === 1 //false
3.空值合并运算符
来自 undefined 或 null 值的另一个问题是,如果我们想要的变量为 undefined 或 null 则必须给变量设置默认值。例如:
const a = b || 123;
当使用 || 运算符将 b 设置为 a 时,如果 b 被定义为 undefined,我们必须设置一个默认值。运算符 || 的问题在于,所有类似于 0,false 或空字符串之类的值都将被我们不想要的默认值覆盖。
为了解决这个问题,创建了“nullish”合并运算符,用 ?? 表示。有了它,我们仅在第一项为 null 或 undefined 时设置默认值。使用无效的合并运算符,以上表达式将变为:
const a = b ?? 123;
4.可选链运算符
如果要访问对象的深层嵌套属性,则必须通过很长的布尔表达式去检查每个嵌套级别中的属性。必须检查每个级别中定义的每个属性,直到所需的深度嵌套的属性为止,如下代码所示:
let name = user && user.info && user.info.name;
let age = user && user.info && user.info.getAge && user.info.getAge();
如果在任何级别的对象中都有 undefined 或 null 的嵌套对象,如果不进行检查,那么的程序将会崩溃。这意味着我们必须检查每个级别,以确保当它遇到 undefined 或 null 对象时不会崩溃。
使用可选链运算符,只需要使用 ?. 来访问嵌套对象。而且如果碰到的是 undefined 或 null 属性,那么它只会返回 undefined。通过可选链,可以把上面的代码改为:
let name = user?.info?.name;
let age = user?.info?.getAge?.();
5.Promise.allSettled()
Promise.allSettled(iterable);
iterable:一个可迭代的对象,例如Array,其中每个成员都是Promise。
返回一个在所有给定的promise resolved 或者 rejected的promise,并带有一个对象数组,每个对象表示对应的promise结果。
const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'));
const promises = [promise1, promise2];
Promise.allSettled(promises).
then((results) => results.forEach((result) => console.log(result.status)));
// expected output:
// "fulfilled"
// "rejected"
6.dynamic-import
静态 import 和动态 import()
有各自的特点和使用场景。使用静态 import
来初始绘制依赖关系,考虑到按需加载则使用动态 import()
。
static import 是没有括号的,dynamic import() 是带括号的。不注意的可能会混淆。用法的区别:
static import: import xxx from 'xxx' //有声明提升,一般只放在头部位置
dynamic import(): const xxx = import('xxx') //可以放在任何位置
el.onclick = () => {
import(`main.js`)
.then(() => {
//...
})
}
7.globalThis
globalThis
提供了一个标准的方式去获取不同环境下的全局对象。它不像 window
或者 self
这些属性,而是确保可以在有无窗口的环境下都可以正常工作。所以你可以安心的使用 globalThis
,不必担心它的运行环境。
var getGlobal = function () {
if (typeof self !== 'undefined') { return self; }
if (typeof window !== 'undefined') { return window; }
if (typeof global !== 'undefined') { return global; }
throw new Error('unable to locate global object');
};
var globals = getGlobal();
if (typeof globals.setTimeout !== 'function') {
// no setTimeout in this environment!
}
//有了 globalThis 之后,只需要:
if (typeof globalThis.setTimeout !== 'function') {
// no setTimeout in this environment!
}
参考资料:
https://github.com/tc39/proposals/blob/master/finished-proposals.md