前端應(yīng)該掌握的10個(gè) JS 小技巧
大廠技術(shù)??高級(jí)前端??Node進(jìn)階
點(diǎn)擊上方?程序員成長(zhǎng)指北,關(guān)注公眾號(hào)
回復(fù)1,加入高級(jí)Node交流群
大家好,我是 LBJ,今天我們聊聊2022一些值得掌握的新特性!
現(xiàn)在前端發(fā)展很快,各種技術(shù)和框架層出不窮、百花齊放,很多人都喊學(xué)不動(dòng)啦!事實(shí)上JavaScript 作為前端的主要語(yǔ)言,雖然它的發(fā)展很快,每年都會(huì)出一些新特性,但視乎 JavaScript 開發(fā)者的發(fā)展速度更快一些,因?yàn)楹芏嘞鄬?duì)較新的功能都已經(jīng)有很高的采用率
下面來(lái)看看那些具有較高采用率的新特性,2022你應(yīng)該了解的10個(gè) JS 小技巧
正文
1. 用??代替||,用于判斷運(yùn)算符左側(cè)的值為null或undefined時(shí),才返回右側(cè)的值
??運(yùn)算符是 ES2020 引入,也被稱為null判斷運(yùn)算符( Nullish coalescing operator)
它的行為類似||,但是更嚴(yán)
||運(yùn)算符是左邊是空字符串或false或0等falsy值,都會(huì)返回后側(cè)的值。而??必須運(yùn)算符左側(cè)的值為null或undefined時(shí),才會(huì)返回右側(cè)的值。因此0||1的結(jié)果為1,0??1的結(jié)果為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. 使用?.簡(jiǎn)化&&和三元運(yùn)算符
?.也是ES2020 引入,有人稱為鏈判斷運(yùn)算符(optional chaining operator)
?.直接在鏈?zhǔn)秸{(diào)用的時(shí)候判斷,判斷左側(cè)的對(duì)象是否為null或undefined,如果是的,就不再往下運(yùn)算,返回undefined,如果不是,則返回右側(cè)的值
例如
var?street?=?user.address?&&?user.address.street;
var?fooInput?=?myForm.querySelector('input[name=foo]')
var?fooValue?=?fooInput???fooInput.value?:?undefined
//?簡(jiǎn)化
var?street?=?user.address?.street
var?fooValue?=?myForm.querySelector('input[name=foo]')?.value
注:常見寫法
obj?.prop? 對(duì)象屬性obj?.[expr]? 對(duì)象屬性func?.(...args)? 函數(shù)或?qū)ο蠓椒ǖ恼{(diào)用
瀏覽器支持情況

3. 使用動(dòng)態(tài)導(dǎo)入import()實(shí)現(xiàn)按需加載(優(yōu)化靜態(tài)import)
我們可以使用 import?語(yǔ)句初始化的加載依賴項(xiàng)
import?defaultExport?from?"module-name";
import?*?as?name?from?"module-name";
//...
但是靜態(tài)引入的import?語(yǔ)句需要依賴于 type="module" 的script標(biāo)簽,而且有的時(shí)候我們希望可以根據(jù)條件來(lái)按需加載模塊,比如以下場(chǎng)景:
當(dāng)靜態(tài)導(dǎo)入的模塊很明顯的降低了代碼的加載速度且被使用的可能性很低,或者并不需要馬上使用它 當(dāng)靜態(tài)導(dǎo)入的模塊很明顯的占用了大量系統(tǒng)內(nèi)存且被使用的可能性很低 當(dāng)被導(dǎo)入的模塊,在加載時(shí)并不存在,需要異步獲取 當(dāng)被導(dǎo)入的模塊有副作用,這些副作用只有在觸發(fā)了某些條件才被需要時(shí)
這個(gè)時(shí)候我們就可以使用動(dòng)態(tài)引入import(),它跟函數(shù)一樣可以用于各種地方,返回的是一個(gè)?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)簡(jiǎn)化 async 函數(shù)
其實(shí)上面的代碼就有用到
let?module?=?await?import('/modules/my-module.js');
頂層 await?允許開發(fā)者在?async?函數(shù)外部使用?await?字段
因此
//以前
(async?function?()?{
??await?Promise.resolve(console.log('??'));
??//?→???
})();
//簡(jiǎn)化后
await?Promise.resolve(console.log('??'));
瀏覽器支持情況

5. 使用String.prototype.replaceAll()簡(jiǎn)化replace一次性替換所有子字符串
String.prototype.replaceAll()用法與String.prototype.replace()類似
但是replace僅替換第一次出現(xiàn)的子字符串,而replaceAll會(huì)替換所有
例如需要替換所有a為A:
//?以前
console.log('aaa'.replace(/a/g,'A'))?//AAA
//?簡(jiǎn)化后
console.log('aaa'.replaceAll('a','A'))?//AAA
瀏覽器支持情況

6. 使用Proxy替代Object.defineProperty
為什么使用 Proxy 替代 Object.defineProperty,簡(jiǎn)單總結(jié)Proxy的幾點(diǎn)優(yōu)勢(shì)
Proxy 是對(duì)整個(gè)對(duì)象的代理,而 Object.defineProperty 只能代理某個(gè)屬性 對(duì)象上新增屬性,Proxy 可以監(jiān)聽到,Object.defineProperty 不能 數(shù)組新增修改,Proxy 可以監(jiān)聽到,Object.defineProperty 不能 若對(duì)象內(nèi)部屬性要全部遞歸代理,Proxy 可以只在調(diào)用的時(shí)候遞歸,而 Object.definePropery 需要一次完成所有遞歸,性能比 Proxy 差
使用也很簡(jiǎn)單,Proxy本質(zhì)是構(gòu)造函數(shù),通過new即可產(chǎn)生對(duì)象,它接收兩個(gè)參數(shù):
target表示的就是要攔截(代理)的目標(biāo)對(duì)象handler是用來(lái)定制攔截行為(13種)
例如響應(yīng)式reactive的基本實(shí)現(xiàn):
function?reactive(obj)?{
????return?new?Proxy(obj,?{
????????get(target,?key)?{
????????????//?可以做依賴收集
????????????track(target,?key)
????????????return?target[key]
????????},
????????set(target,?key,?val)?{
????????????target[key]?=?val
????????????//?觸發(fā)依賴
????????????trigger(target,?key)
????????}
????})
}
瀏覽器支持情況

7. Promise.any快速獲取一組Promise實(shí)例中第一個(gè)fulfilled的promise
Promise.any 接收一組Promise實(shí)例作為參數(shù)
只要其中的一個(gè)? promise?成功,就返回那個(gè)已經(jīng)成功的?promise如果這組可迭代對(duì)象中,沒有一個(gè)? promise?成功,就返回一個(gè)失敗的?promise?和?AggregateError?類型的實(shí)例
寫法推薦
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支持大整數(shù)計(jì)算問題
ES2020[1]?引入了一種新的數(shù)據(jù)類型 BigInt,用來(lái)表示任意位數(shù)的整數(shù)
例如
//?超過?53?個(gè)二進(jìn)制位的數(shù)值(相當(dāng)于?16?個(gè)十進(jìn)制位),無(wú)法保持精度
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來(lái)聲明一個(gè)大整數(shù),還可以使用數(shù)字后面加n的形式,如
1234?//?普通整數(shù)
1234n?//?BigInt
需要了解BigInt數(shù)字操作時(shí)的支持情況,以免踩坑
| 操作 | 是否支持 |
|---|---|
| 單目?(+) 運(yùn)算符 | N |
+、*、-、**、%?運(yùn)算符 | Y |
| \ 除法運(yùn)算符 | 帶小數(shù)的運(yùn)算會(huì)被取整 |
>>>?無(wú)符號(hào)右移位操作符 | N |
| 其他位移操作符 | Y |
| 與 Number 混合運(yùn)算 | N(必須轉(zhuǎn)換為同類型) |
| Math 對(duì)象方法 | N |
| Number 與 BigInt 比較(排序) | Y(寬松相等 ==) |
| Boolean 表現(xiàn) | 類型 Number 對(duì)象 |
| JSON 中使用 | N |
瀏覽器支持情況

9. 使用Array.prototype.at()簡(jiǎn)化arr.length
Array.prototype.at()接收一個(gè)正整數(shù)或者負(fù)整數(shù)作為參數(shù),表示獲取指定位置的成員
參數(shù)正數(shù)就表示順數(shù)第幾個(gè),負(fù)數(shù)表示倒數(shù)第幾個(gè),這可以很方便的某個(gè)數(shù)組末尾的元素
例如
var?arr?=?[1,?2,?3,?4,?5]
//?以前獲取最后一位
console.log(arr[arr.length-1])?//5
//?簡(jiǎn)化后
console.log(arr.at(-1))?//?5
10. 使用哈希前綴#將類字段設(shè)為私有
在類中通過哈希前綴#標(biāo)記的字段都將被私有,子類實(shí)例將無(wú)法繼承
例如
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都被私有化了,在實(shí)例中無(wú)法獲取到
結(jié)語(yǔ)
很多新特性都有很多人在用了,特別是??和?.以及動(dòng)態(tài)引入import(),不知道你都用過哪些?
好了,以上就是本文的相關(guān)內(nèi)容,如有問題歡迎指出~??
關(guān)于本文
作者:LBJ
https://juejin.cn/post/7072274726940311588
最后
Node 社群
我組建了一個(gè)氛圍特別好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你對(duì)Node.js學(xué)習(xí)感興趣的話(后續(xù)有計(jì)劃也可以),我們可以一起進(jìn)行Node.js相關(guān)的交流、學(xué)習(xí)、共建。下方加 考拉 好友回復(fù)「Node」即可。
如果你覺得這篇內(nèi)容對(duì)你有幫助,我想請(qǐng)你幫我2個(gè)小忙:
1. 點(diǎn)個(gè)「在看」,讓更多人也能看到這篇文章 2. 訂閱官方博客?www.inode.club?讓我們一起成長(zhǎng) 點(diǎn)贊和在看就是最大的支持??
