>[success] # ES11 -- 空值合并运算符(Nullish coalescing Operator) 1. 空值合并操作符'**??**' 和 "逻辑操作符 **||** 的区别,空值合并操作符只有当左面操作数为 **null 或者 undefined 时**,返回其**右侧操作数**,否则返回**左侧操作数**,逻辑操作符 **|| 是一个布尔逻辑运算符,左侧的操作数会被强制转换成布尔值用于求值**。任何假值 **(0, '', NaN, null, undefined)** 都返回右侧值 >[danger] ##### 案例 ~~~ 1.可以看出非null 或者 undefined 是不会影响到空值合并操作符的 ~~~ ~~~ let count = 0; let text = ""; let qty = count || 42; let message = text || "hi!"; console.log(qty); // 42 console.log(message); // "hi!" let qty1 = count ?? 42 let message1 = text ?? "hi!" console.log(qty1); // 0 console.log(message1); // 空字符 ~~~ * 案例 当返回值是null 或undefined 也会出现短路效果 ~~~ function A() { console.log('函数 A 被调用了'); return undefined; } function B() { console.log('函数 B 被调用了'); return false; } function C() { console.log('函数 C 被调用了'); return "foo"; } console.log( A() ?? C() ); // 依次打印 "函数 A 被调用了"、"函数 C 被调用了"、"foo" // 因为A返回了undefined 所以执行右侧 console.log( B() ?? C() ); // 依次打印 "函数 B 被调用了"、"false" // 因为左侧返回的是非undefined 和 null 因此只执行左侧 ~~~ >[danger] ##### 注意 1. **将 ?? 直接与 AND(&&)和 OR(||)操作符组合使用是不可取的**。 ~~~ null || undefined ?? "foo"; // 抛出 SyntaxError true || undefined ?? "foo"; // 抛出 SyntaxError ~~~ >[success] # ES11 -- 可选链 Optional chaining ~~~ 1.当对象某个属性不存时候,不会引起错误,该表达式短路返回值是 、 undefined。与函数调用一起使用时,如果给定的函数不存在,则返回 undefined 2.'obj.name?.age' 以这个案例说明,可选链保证的是'obj.name'这个值 既不是undefined 也不是null 的情况下才能调用name,如果是的话就返回 undefined· 3.'可选链与函数使用',函数调用时如果被调用的方法不存在,使用可选链可 以使表达式自动返回undefined而不是抛出一个异常,但是如果存在却不是 一个函数会报错 let result = someInterface.customMethod?.(); 4.可选链不能进行赋值操作 let object = {}; object?.property = 1; // Uncaught SyntaxError: Invalid left-hand side in assignment 5.'断路计算'下面的例子如果左面操作是null 或者undefined 就形成断路 后面的属性也不会进行计算 let potentiallyNullObj = null; let x = 0; let prop = potentiallyNullObj?.[x++]; console.log(x); // x 将不会被递增,依旧输出 0 6.语法 obj?.prop obj?.[expr] arr?.[index] func?.(args) ~~~ >[danger] ##### 案例 ~~~ const adventurer = { name: 'Alice', cat: { name: 'Dinah' } }; const dogName = adventurer.dog?.name; console.log(dogName); // undefined console.log(adventurer.someNonExistentMethod?.()); // undefined function fn(callback){ return callback?.() // callback && callback() } ~~~ * 与空值合并操作符一起使用 ~~~ let customer = { name: "Carl", details: { age: 82 } }; let customerCity = customer?.city ?? "暗之城"; console.log(customerCity); // “暗之城” ~~~ >[danger] ##### 注意点 1. **可选链不能用于赋值** ~~~ let object = {}; object?.property = 1; // Uncaught SyntaxError: Invalid left-hand side in assignment ~~~ >[success] # ES11 -- globalThis 1. **ES2020引入了globalThis对象**,它提供了跨环境访问全局对象的标准方法中提出要提供全局变量,简单说在浏览器中为`window`,在node环境中为`global`,但现在为统一目前已经指定了对应的标准,称之为**globalThis** 2. 在不同js 环境中总是存在不同全局变量标准,往往在**浏览器**中**window**或者**frames**,在**WebWorkers**中**self**,在**Node**中**global** 3. 下面代码在浏览器中打印你会得到**true** 4. 使用场景假设我们的环境是一个浏览器,我们将在这里使用 window。如果脚本可能在其他环境中运行,最好使用**globalThis** >[success] # ES11 -- BigInt 1. **`BigInt`** 是一种内置对象,它提供了一种方法来表示大于 `2的53次方 - 1` 的整数。这原本是 Javascript中可以用 `Number` 表示的最大数字。**`BigInt`** 可以表示任意大的整数。 2. 使用数字后面增加n ~~~ const bigInt = 9007199254740993n console.log(bigInt) console.log(typeof bigInt) // bigint // `BigInt` 和 [`Number`]不是严格相等的,但是宽松相等的。 console.log(1n == 1) // true console.log(1n === 1) // false // `Number` 和 `BigInt` 可以进行比较。 1n < 2 // true 2n > 1 // true ~~~ 3. 使用 BigInt 函数 ~~~ const bigIntNum = BigInt(9007199254740993n) console.log(bigIntNum) // 9007199254740993n ~~~ 4. 做运算,`BigInt`不能用于 `Math `对象中的方法;不能和任何 `Number`实例混合运算,两者必须转换成**同一种类型**。在两种类型来回转换时要小心,因为 `BigInt `变量在转换成 `Number`变量时可能会丢失精度 ~~~ let number = BigInt(2); let a = number + 2n; // 4n let b = number * 10n; // 20n let c = number - 10n; // -8n console.log(a); console.log(b); console.log(c); ~~~ >[success] # ES11 -- String.prototype.matchAll() 1. **`matchAll()`** 方法返回一个包含所有匹配正则表达式的结果及分组捕获组的迭代器。 ~~~ const regexp = /t(e)(st(\d?))/g; const str = 'test1test2'; const array = [...str.matchAll(regexp)]; console.log(array[0]); // ["test1", "e", "st1", "1"] console.log(array[1]); // ["test2", "e", "st2", "2"] ~~~ >[success] # ES11 -- Promise.allSettled() 1. **Promise.all()** 具有并发执行异步任务的能力。但它的最大问题就是如果其中某个任务出现异常(reject),所有任务都会挂掉,**Promise直接进入reject 状态** 2. **Promise.allSettled**,无论一个任务正常或者异常,都会返回对应的的状态 ~~~ const promise1 = () => { return new Promise((resolve, reject) => { setTimeout(() => { resolve("promise1"); // reject("error promise1 "); }, 3000); }); }; const promise2 = () => { return new Promise((resolve, reject) => { setTimeout(() => { resolve("promise2"); // reject("error promise2 "); }, 1000); }); }; const promise3 = () => { return new Promise((resolve, reject) => { setTimeout(() => { // resolve("promise3"); reject("error promise3 "); }, 2000); }); }; // Promise.all 会走到catch里面 Promise.all([promise1(), promise2(), promise3()]) .then((res) => { console.log(res); }) .catch((error) => { console.log("error", error); // error promise3 }); // Promise.allSettled 不管有没有错误,三个的状态都会返回 Promise.allSettled([promise1(), promise2(), promise3()]) .then((res) => { console.log(res); // 打印结果 // [ // {status: 'fulfilled', value: 'promise1'}, // {status: 'fulfilled',value: 'promise2'}, // {status: 'rejected', reason: 'error promise3 '} // ] }) .catch((error) => { console.log("error", error); }); ~~~ >[success] # Dynamic Import(按需 import) 1. **import()** 可以在需要的时候,再加载某个模块。 ~~~ button.addEventListener('click', event => { import('./dialogBox.js') .then(dialogBox => { dialogBox.open(); }) .catch(error => { /* Error handling */ }) }); ~~~