ECMAScript 11 學習筆記
Promise.allSettled()
Promise.allSettled()
方法回傳一個在所有給定的 promise 都已經 fulfilled 或 rejected 後的 promise,並帶有一個物件陣列,每個物件代表對應的 promise 結果。
有時候,我們希望等到一組非同步操作都結束了,不管每一個操作是成功還是失敗,再進行下一步操作。而 Promise.all()
方法只適合所有非同步操作都成功的情況,如果有一個操作失敗,就無法滿足要求。
為了解決這個問題,ES2020 引入了 Promise.allSettled()
方法,用來確定一組非同步操作是否都結束了(不管成功或失敗)。
Promise.allSettled([ajax('1.json'), ajax('2.json'), ajax('33.json')]).then((res) => {
console.log(res);
const data = res.filter((item) => item.status === 'fulfilled');
console.log(data.flatMap((item) => item.value.data));
});
module 新增
動態匯入 import()
標準用法的
import
匯入的模組是靜態的,會使所有被匯入的模組,在載入時就被編譯(無法做到按需編譯,降低首頁載入速度)。有些場景中,你可能會希望根據條件匯入模組或者按需匯入模組,這時你可以使用動態匯入代替靜態匯入。
<body>
<button id="login">login</button>
<script type="module">
function login() {
return '管理員';
// return '普通用戶';
}
const obtn = document.querySelector('#login');
obtn.onclick = function () {
let role = login();
console.log(role);
render(role);
};
async function render(role) {
if (role === '管理員') {
const res = await import('./1.js');
console.log(res);
} else {
const res = await import('./2.js');
console.log(res);
}
}
</script>
</body>
// 1.js
console.log('1.js 載入了');
export default {
name: '管理員模組',
};
export function test() {}
// 2.js
console.log('2.js 載入了');
export default {
name: '普通用戶模組',
};
import.meta
import.meta
會回傳一個物件,有一個 url
屬性,回傳目前模組的 url 路徑,只能在模組內部使用。
// 在剛剛的 2.js 裡打印一下 import.meta
console.log('2.js 載入了', import.meta);
export default {
name: '普通用戶模組',
};
export * as obj from 'module'
export * as obj from 'module';
// 等同於
import * as obj from 'module';
export { obj };
字串的 matchAll 方法
matchAll()
方法回傳一個包含所有對應正規表達式的結果的迭代器。可以使用for...of
遍歷,或者使用展開運算子(...
)或者Array.from
轉換成陣列。
const str = `
<ul>
<li>11111</li>
<li>22222</li>
<li>33333</li>
<li>55555</li>
</ul>
`;
const reg = /<li>(?<content>.*)<\/li>/g;
// 使用 exec
let match = null;
const list = [];
while ((match = reg.exec(str))) {
list.push(match.groups.content);
}
console.log(list);
// prints: ['11111', '22222', '33333', '55555']
// 使用 matchAll
const iObj = str.matchAll(reg);
console.log([...iObj]);
BigInt
JavaScript 能夠準確表示的整數範圍在 -2^53 到 2^53 之間(不含兩個端點),超過這個範圍,無法精確表示這個值,這使得 JavaScript 不適合進行科學和金融方面的精確計算。
9007199254740992 // 9007199254740992
9007199254740993 // 9007199254740992
// 超過 53 個二進位的數值,無法保持精度
Math.pow(2, 53) === Math.pow(2, 53) + 1 // true
// 超過 2 的 1024 次方的數值,無法表示
Math.pow(2, 1024) // Infinity
為了與 Number 型別區分,BigInt 型別的資料必須加上一個後綴 n
。
1234 // 普通整數
1234n // BigInt
// BigInt 的運算
1n + 2n // 3n
BigInt 函式
JavaScript 原生提供 BigInt
函式,可以用它生成 BigInt 型別的數值。轉換規則基本與 Number()
一致,將其他型別的值轉為 BigInt。
BigInt(123) // 123n
BigInt('123') // 123n
BigInt(false) // 0n
BigInt(true) // 1n
使用 BigInt 來計算大整數:
console.log(BigInt(2 ** 53) + BigInt(1)); // 9007199254740993n
console.log(BigInt(2 ** 53) + BigInt(2)); // 9007199254740994n
console.log(BigInt(2 ** 53) + BigInt(3)); // 9007199254740995n
補充:json-bigint
json-bigint 是一個可以用來處理帶有大整數資料的 json 格式轉換的套件。
npm i json-bigint
假設今天後端傳回來的 id 不是字串而是一個很大的數值時,可以使用這個套件來協助處理。
import JSONbig from 'json-bigint';
const JSONBigIntStr = JSONbig({ storeAsString: true });
const JSONBigIntNative = JSONbig({ useNativeBigInt: true });
const jsonStr = `
{
"id": 9007199254740993,
"list": []
}
`;
console.log(JSONBigIntStr.parse(jsonStr).id); // 9007199254740993 (字串)
console.log(JSONBigIntNative.parse(jsonStr).id); // 9007199254740993n (BigInt)
globalThis
globalThis
提供了一個標準的方式來獲取不同環境下的全域this
物件(也就是全域物件自己)。不像window
或者self
這些屬性,它確保可以在有無窗口的各種環境下正常工作。所以,你可以安心的使用globalThis
,不必擔心它的執行環境。為便於記憶,只需記住全域作用域中的this
就是globalThis
。
- 瀏覽器裡面,全域(頂層)物件是
window
,但 Node 和 Web Worker 沒有window
。 - 瀏覽器和 Web Worker 裡面,
self
也指向全域物件,但是 Node 沒有self
。 - Node 裡面,全域物件是
global
,但其他環境都不支持。
// 以前
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');
};
const globals = getGlobal();
if (globals.document) {
console.log('執行 dom 操作');
} else {
console.log('不能執行 dom 操作');
}
// 現在
if (globalThis.document) {
console.log('執行 dom 操作');
} else {
console.log('不能執行 dom 操作');
}
Nullish coalescing operator (??)
nullish coalescing operator 中文直翻的話叫做「空值合併運算子」,是在 ES2020 引入的一個新的 Null 判斷運算子。在 JavaScript 的表示方式為兩個問號
??
,它的行為類似於||
,但是只有運算子左側的值為null
或undefined
時,才會回傳右側的值。
const obj = {
name: 'sheep',
introduction: 0,
};
console.log(obj.introduction || '這人很懶,什麼都沒寫'); // 這人很懶,什麼都沒寫
console.log(obj.introduction ?? '這人很懶,什麼都沒寫'); // 0
console.log(NaN || 'yo'); // yo
console.log(NaN ?? 'yo'); // NaN
??
和 ||
的區別是什麼呢?
它們兩個最大的區別就是 ''
和 0
,??
的左側為 ''
或是 0
的時候,依然會回傳左側的值;||
會對左側的資料進行 boolean
型別轉換,所以 ''
和 0
會被轉換成 false
,回傳右側的值。
Optional chaining (?.)
可選串連(
?.
),前面的值如果是null
或undefined
,則不再執行後面的,直接回傳undefined
。
const obj = {
id: '12345',
// profile: {
// name: 'sheep',
// },
};
// ES11 以前
console.log(obj && obj.profile && obj.profile.name);
// 有了 ?. 之後
console.log(obj?.profile?.name);