目录
Promise.allSettled
Promise.all有并发执行异步任务的能力,但是如果其中某个任务出现异常(reject),所有任务都会挂掉,Promise 直接进入 reject 状态。
Promise.allSettled并发任务中,无论一个任务正常或者异常,都会返回对应的的状态(fulfilled 或者 rejected)与结果(业务 value 或者 拒因 reason),在 then 里面通过 filter 来过滤出想要的业务逻辑结果,这就能最大限度的保障业务当前状态的可访问性。
Promise.allSettled([
Promise.reject({code: 500, msg: '服务异常'}),
Promise.resolve({ code: 200, list: []}),
Promise.resolve({code: 200, list: []})
]).then((ret) => {
/*
0: {status: "rejected", reason: {...}}
1: {status: "fulfilled", value: {...}}
2: {status: "fulfilled", value: {...}}
*/
// 过滤掉 rejected 状态,尽可能多的保证页面区域数据渲染
RenderContent(ret.filter((el) => {
return el.status !== 'rejected';
}));
});
可选链
可选链可以用来替代冗长的安全链式操作,在查询具有多层级的对象时,不再需要进行冗余的各种前置校验。
const street = user && user.address && user.address.street;
// 可选链
const street = user?.address?.street;
注意操作符是?.而不是单?,在函数调用中有些奇怪alert?.(),这是为了与三目运算符中的?区分开
空值合并运算符
在JS中,空字符串、0 等,当进行逻辑操作符判断时,会自动转化为 false,这个时候使用||遇到任一假值都会返回右侧的默认值。与 || 相比,空值合并运算符 ?? 只会在左边的值严格等于 null 或 undefined 时起作用。
actualValue ?? defaultValue
// 等价于
actualValue !== undefined && actualValue !== null ? actualValue : defaultValue
for in标准化
JavaScript 中通过for-in遍历对象时 key 的顺序是不确定的,因为规范没有明确定义,并且能够遍历原型属性让for-in的实现机制变得相当复杂,不同 JavaScript 引擎有各自根深蒂固的不同实现,很难统一
所以 ES2020 不要求统一属性遍历顺序,而是对遍历过程中的一些特殊 Case 明确定义了一些规则:
遍历不到 Symbol 类型的属性
遍历过程中,目标对象的属性能被删除,忽略掉尚未遍历到却已经被删掉的属性
遍历过程中,如果有新增属性,不保证新的属性能被当次遍历处理到
属性名不会重复出现(一个属性名最多出现一次)
目标对象整条原型链上的属性都能遍历到
export * as ns from “mod”
这是对 ES 规范的有力补充,它允许开发者以新名称导出另一模块的命名空间外部对象。
同属于export … from …形式的聚合导出,作用上类似于:
import * as ns from "mod";
export {ns};
但不会在当前模块作用域引入目标模块的各个 API 变量
import.meta
import.meta用来透出模块特定的元信息,import.meta本身是个对象,原型为null。
比如:
模块的 URL 或文件名:例如Node.js里的__dirname、__filename
所处的script标签:例如浏览器支持的document.currentScript
入口模块:例如 Node.js 里的process.mainModule
基本数据类型BigInt
JS中Number类型只能安全地表示-9007199254740991 (-(253-1))和9007199254740991(253-1)之间的整数,任何超出此范围的整数值都可能失去精度。
BigInt提供了一种方法来表示大于 253 - 1 的整数。这原本是 Javascript中可以用 Number 表示的最大数字。BigInt 可以表示任意大的整数。
可以用在一个整数字面量后面加 n 的方式定义一个 BigInt ,如:10n,或者调用函数BigInt()。
const theBiggestInt = 9007199254740991n;
const alsoHuge = BigInt(9007199254740991); // 9007199254740991n
const hugeString = BigInt("9007199254740991"); // 9007199254740991n
const hugeHex = BigInt("0x1fffffffffffff"); // 9007199254740991n
const hugeBin = BigInt("0b11111111111111111111111111111111111111111111111111111"); // 9007199254740991n
BigInt类似于 Number ,但是也有几个关键的不同点:不能用于 Math 对象中的方法;不能和任何 Number 实例混合运算,两者必须转换成同一种类型。在两种类型来回转换时要小心,因为 BigInt 变量在转换成 Number 变量时可能会丢失精度。
加上ES6新增的Symbol一共有七种基本数据类型,分别是: String、Number、Boolean、Null、Undefined、BigInt。
globalThis
全局属性 globalThis 包含全局的 this 值,类似于全局对象。在以前,从不同的 JavaScript 环境中获取全局对象需要不同的语句。在 Web 中,可以通过 window、self 或者 frames 取到全局对象,但是在 Web Workers 中,只有 self 可以。在 Node.js 中,它们都无法获取,必须使用 global。
在松散模式下,可以在函数中返回 this 来获取全局对象,但是在严格模式和模块环境下,this 会返回 undefined。globalThis 提供了一个标准的方式来获取不同环境下的全局 this 对象(也就是全局对象自身)。不像 window 或者 self 这些属性,它确保可以在有无窗口的各种环境下正常工作。所以,你可以安心的使用 globalThis,不必担心它的运行环境。为便于记忆,你只需要记住,全局作用域中的 this 就是 globalThis。
function canMakeHTTPRequest() {
return typeof globalThis.XMLHttpRequest === "function";
}
console.log(canMakeHTTPRequest()); // expected output (in a browser): true
import()
标准用法的import导入的模块是静态的,会使所有被导入的模块,在加载时就被编译(无法做到按需编译,降低首页加载速度)。有些场景中,你可能希望根据条件导入模块或者按需导入模块,这时你可以使用动态导入代替静态导入。
import()支持动态加载模块。import命令能够接受什么参数,import()函数就能接受什么参数,两者区别主要是后者为动态加载。import是静态加载资源,编译时放到代码块最顶层。import()函数则是动态按需加载返回Promise 对象。import()函数可以用在任何地方,不仅仅是模块,非模块的脚本也可以使用。
import()函数它是运行时执行,也就是说,什么时候运行到这一句,就会加载指定的模块。
import("/modules/my-module.js").then((module) => {
// Do something with the module.
});
// 这种使用方式也支持 await 关键字
let module = await import("/modules/my-module.js");
私有的实例方法和访问器
新的语法字符 #octothorpe(hash tag)现在用于直接在类主体的范围内定义变量,函数,getter 和 setter以及构造函数和类方法。通过在变量或函数前面添加一个简单的哈希符号,我们可以将它们完全保留为类内部使用.
class Raven extends Bird {
#state = { eggs: 10};
// getter
get #eggs() {
return state.eggs;
}
// setter
set #eggs(value) {
this.#state.eggs = value;
}
#lay() {
this.#eggs++;
}
constructor() {
super();
this.#lay.bind(this);
}
#render() {
/* paint UI */
}
}