2022 前端應該掌握的 10 個 JS 小技巧
來自:掘金,作者:LBJ 鏈接:https://juejin.cn/post/7072274726940311588
你知道 0 ?? 1
等於多少嗎?
大家好,我是 LBJ
,今天我們聊聊2022
一些值得掌握的新特性!
現在前端發展很快,各種技術和框架層出不窮、百花齊放,很多人都喊學不動啦!事實上JavaScript
作爲前端的主要語言,雖然它的發展很快,每年都會出一些新特性,但視乎 JavaScript
開發者的發展速度更快一些,因爲很多相對較新的功能都已經有很高的採用率
下面來看看那些具有較高採用率的新特性,2022
你應該瞭解的10
個 JS
小技巧
1. 用??
代替||
,用於判斷運算符左側的值爲null
或undefined
時,才返回右側的值
??
運算符是 ES2020
引入,也被稱爲null
判斷運算符 (Nullish coalescing operator)
它的行爲類似||
,但是更嚴
||
運算符是左邊是空字符串或false
或0
等 falsy 值,都會返回後側的值。而??
必須運算符左側的值爲null
或undefined
時,纔會返回右側的值。因此 0||1 的結果爲 1,0??1 的結果爲 0
例如
const response = {
settings: {
nullValue: null,
height: 400,
animationDuration: 0,
headerText: '',
showSplashScreen: false
}
};
const undefinedValue = response.settings.undefinedValue ?? 'some other default'; // result: 'some other default'
const nullValue = response.settings.nullValue ?? 'some other default'; // result: 'some other default'
const headerText = response.settings.headerText ?? 'Hello, world!'; // result: ''
const animationDuration = response.settings.animationDuration ?? 300; // result: 0
const showSplashScreen = response.settings.showSplashScreen ?? true; // result: false
複製代碼
瀏覽器支持情況
2. 使用?.
簡化&&
和三元運算符
?.
也是 ES2020 引入,有人稱爲鏈判斷運算符(optional chaining operator)
?.
直接在鏈式調用的時候判斷,判斷左側的對象是否爲null
或undefined
,如果是的,就不再往下運算,返回 undefined,如果不是,則返回右側的值
例如
var street = user.address && user.address.street;
var fooInput = myForm.querySelector('input[name=foo]')
var fooValue = fooInput ? fooInput.value : undefined
// 簡化
var street = user.address?.street
var fooValue = myForm.querySelector('input[name=foo]')?.value
複製代碼
注:常見寫法
-
obj?.prop
對象屬性 -
obj?.[expr]
對象屬性 -
func?.(...args)
函數或對象方法的調用
瀏覽器支持情況
3. 使用動態導入 import() 實現按需加載(優化靜態 import)
我們可以使用 import
語句初始化的加載依賴項
import defaultExport from "module-name";
import * as name from "module-name";
//...
複製代碼
但是靜態引入的import
語句需要依賴於 type="module"
的script
標籤,而且有的時候我們希望可以根據條件來按需加載模塊,比如以下場景:
-
當靜態導入的模塊很明顯的降低了代碼的加載速度且被使用的可能性很低,或者並不需要馬上使用它
-
當靜態導入的模塊很明顯的佔用了大量系統內存且被使用的可能性很低
-
當被導入的模塊,在加載時並不存在,需要異步獲取
-
當被導入的模塊有副作用,這些副作用只有在觸發了某些條件才被需要時
這個時候我們就可以使用動態引入import()
,它跟函數一樣可以用於各種地方,返回的是一個 promise
基本使用如下兩種形式
//形式 1
import('/modules/my-module.js')
.then((module) => {
// Do something with the module.
});
//形式2
let module = await import('/modules/my-module.js');
複製代碼
瀏覽器支持情況
4. 使用頂層 await(top-level await)簡化 async 函數
其實上面的代碼就有用到
let module = await import('/modules/my-module.js');
複製代碼
頂層 await
允許開發者在 async
函數外部使用 await
字段
因此
//以前
(async function () {
await Promise.resolve(console.log('🎉'));
// → 🎉
})();
//簡化後
await Promise.resolve(console.log('🎉'));
複製代碼
瀏覽器支持情況
5. 使用 String.prototype.replaceAll() 簡化 replace 一次性替換所有子字符串
String.prototype.replaceAll()
用法與String.prototype.replace()
類似
但是replace
僅替換第一次出現的子字符串,而replaceAll
會替換所有
例如需要替換所有 a 爲 A:
// 以前
console.log('aaa'.replace(/a/g,'A')) //AAA
// 簡化後
console.log('aaa'.replaceAll('a','A')) //AAA
複製代碼
瀏覽器支持情況
6. 使用 Proxy 替代 Object.defineProperty
爲什麼使用 Proxy
替代 Object.defineProperty
,簡單總結Proxy
的幾點優勢
-
Proxy 是對整個對象的代理,而 Object.defineProperty 只能代理某個屬性
-
對象上新增屬性,Proxy 可以監聽到,Object.defineProperty 不能
-
數組新增修改,Proxy 可以監聽到,Object.defineProperty 不能
-
若對象內部屬性要全部遞歸代理,Proxy 可以只在調用的時候遞歸,而 Object.definePropery 需要一次完成所有遞歸,性能比 Proxy 差
使用也很簡單,Proxy
本質是構造函數,通過 new 即可產生對象,它接收兩個參數:
-
target
表示的就是要攔截(代理)的目標對象 -
handler
是用來定製攔截行爲(13 種)
例如響應式reactive
的基本實現:
function reactive(obj) {
return new Proxy(obj, {
get(target, key) {
// 可以做依賴收集
track(target, key)
return target[key]
},
set(target, key, val) {
target[key] = val
// 觸發依賴
trigger(target, key)
}
})
}
複製代碼
瀏覽器支持情況
7. Promise.any 快速獲取一組Promise
實例中第一個fulfilled
的promise
Promise.any
接收一組Promise
實例作爲參數
-
只要其中的一個
promise
成功,就返回那個已經成功的promise
-
如果這組可迭代對象中,沒有一個
promise
成功,就返回一個失敗的promise
和AggregateError
類型的實例
寫法推薦
try {
const first = await Promise.any(promises);
// Any of the promises was fulfilled.
} catch (error) {
// All of the promises were rejected.
}
複製代碼
或者
Promise.any(promises).then(
(first) => {
// Any of the promises was fulfilled.
},
(error) => {
// All of the promises were rejected.
}
);
複製代碼
瀏覽器支持情況
8. 使用 BigInt 支持大整數計算問題
ES2020[1] 引入了一種新的數據類型 BigInt,用來表示任意位數的整數
例如
// 超過 53 個二進制位的數值(相當於 16 個十進制位),無法保持精度
Math.pow(2, 53) === Math.pow(2, 53) + 1 // true
// BigInt
BigInt(Math.pow(2, 53)) === BigInt(Math.pow(2, 53)) + BigInt(1) // false
複製代碼
除了使用 BigInt 來聲明一個大整數,還可以使用數字後面加 n 的形式,如
1234 // 普通整數
1234n // BigInt
複製代碼
需要了解 BigInt 數字操作時的支持情況,以免踩坑
瀏覽器支持情況
9. 使用 Array.prototype.at() 簡化 arr.length
Array.prototype.at()
接收一個正整數或者負整數作爲參數,表示獲取指定位置的成員
參數正數就表示順數第幾個,負數表示倒數第幾個,這可以很方便的某個數組末尾的元素
例如
var arr = [1, 2, 3, 4, 5]
// 以前獲取最後一位
console.log(arr[arr.length-1]) //5
// 簡化後
console.log(arr.at(-1)) // 5
複製代碼
10. 使用哈希前綴#
將類字段設爲私有
在類中通過哈希前綴#
標記的字段都將被私有,子類實例將無法繼承
例如
class ClassWithPrivateField {
#privateField;
#privateMethod() {
return 'hello world';
}
constructor() {
this.#privateField = 42;
}
}
const instance = new ClassWithPrivateField()
console.log(instance.privateField); //undefined
console.log(instance.privateMethod); //undefined
複製代碼
可以看到,屬性privateField
和方法privateMethod
都被私有化了,在實例中無法獲取到
最後
很多新特性都有很多人在用了,特別是??
和?.
以及動態引入import()
,不知道你都用過哪些?
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/YyuZFDpXhZBq5Ua7fpcqNA