您好,登錄后才能下訂單哦!
JavaScript優(yōu)化技巧都有哪些,相信很多沒(méi)有經(jīng)驗(yàn)的人對(duì)此束手無(wú)策,為此本文總結(jié)了問(wèn)題出現(xiàn)的原因和解決方法,通過(guò)這篇文章希望你能解決這個(gè)問(wèn)題。
作為開(kāi)發(fā)人員,我們一直在尋找讓我們的代碼更快更好的方法。但在此之前,編寫高性能代碼需要做三件事:
了解語(yǔ)言及其工作原理
基于用例進(jìn)行設(shè)計(jì)
調(diào)試!修復(fù)!重復(fù)
記住這一點(diǎn)
任何傻瓜都可以編寫計(jì)算機(jī)可以理解的代碼,優(yōu)秀的程序員編寫人類可以理解的代碼。
我們來(lái)看看如何使 JavaScript代碼運(yùn)行得更快。
延遲
延遲算法將計(jì)算延遲到需要執(zhí)行時(shí)才執(zhí)行,然后生成結(jié)果。
const someFn = () => { doSomeOperation() return () => { doExpensiveOperation() } } const t = someArray.filter((x) => checkSomeCondition(x)).map((x) => someFn(x)) // 現(xiàn)在,如果有需要在執(zhí)行 t.map((x) => t())
最快的代碼是未執(zhí)行的代碼,所以盡量延遲執(zhí)行。
JavaScript 使用原型繼承,JS 中所有對(duì)象都是Object的實(shí)例。
MDN說(shuō):
嘗試訪問(wèn)對(duì)象的屬性時(shí),不僅會(huì)在對(duì)象上搜索該屬性,還會(huì)在對(duì)象的原型,原型的原型等上搜索該屬性,直到找到匹配屬性名或原型鏈的末端。
對(duì)于每個(gè)屬性,JavaScript引擎都必須遍歷整個(gè)對(duì)象鏈,直到找到匹配項(xiàng)。如果使用不當(dāng),這會(huì)占用大量資源,并影響應(yīng)用程序的性能。
所以不要這樣:
const name = userResponse.data.user.firstname + userResponse.data.user.lastname
而是這樣做:
const user = userResponse.data.user const name = user.firstname + user.lastname
使用臨時(shí)變量來(lái)保存鏈接的屬性,而不是遍歷訪問(wèn)整條鏈。
使用轉(zhuǎn)譯器之前要三思
在上述情況下,userResponse可能不是對(duì)象,如果是對(duì)象,它的屬性 user 也可能不是對(duì)象。所以,在獲取值時(shí)要進(jìn)行檢查:
let name = '' if (userResponse) { const data = userResponse.data if (data && data.user) { const user = data.user if (user.firstname) { name += user.firstname } if (user.lastname) { name += user.firstname } } }
這太啰嗦了。代碼越多,bug 就越明顯。我們能把它縮小嗎?當(dāng)然,可以使用 JS 中可選的鏈接、解構(gòu)賦值來(lái)優(yōu)化它。
const user = userResponse?.data?.user const { firstname = '', lastname = ''} = user const name = firstname + lastname
是不是很靈活地,簡(jiǎn)短?不要使用這個(gè)要注意,Babel 會(huì)按照以下方式進(jìn)行轉(zhuǎn)換:
'use strict' var _userResponse, _userResponse$data var user = (_userResponse = userResponse) === null || _userResponse === void 0 ? void 0 : (_userResponse$data = _userResponse.data) === null || _userResponse$data === void 0 ? void 0 : _userResponse$data.user var _user$firstname = user.firstname, firstname = _user$firstname === void 0 ? '' : _user$firstname, _user$lastname = user.lastname, lastname = _user$lastname === void 0 ? '' : _user$lastname var name = firstname + lastname
當(dāng)使用轉(zhuǎn)譯時(shí),確保你選擇了一個(gè)更適合你的用例的。
了解SMI和堆號(hào)
數(shù)字很奇怪,ECMAScript將數(shù)字標(biāo)準(zhǔn)化為64位浮點(diǎn)值,也稱為雙精度浮點(diǎn)或Float64表示形式。
如果 JS 引擎以Float64表示形式存儲(chǔ)數(shù)字,則將導(dǎo)致巨大的性能低下。JS 引擎對(duì)數(shù)字進(jìn)行抽象,使其行為與Float64完全匹配。與float64運(yùn)算相比,JS 引擎執(zhí)行整數(shù)運(yùn)算的速度要快得多。
有時(shí),我們認(rèn)為像下面這樣寫法可讀比較好:
const maxWidth = '1000' const minWidth = '100' const margin = '10' getWidth = () => ({ maxWidth: maxWidth - margin * 2, minWidth: minWidth - margin * 2, })
評(píng)估局部變量
如果getWidth函數(shù)被多次調(diào)用,那么每次調(diào)用它時(shí)都會(huì)計(jì)算它的值。上面的計(jì)算并不是什么大問(wèn)題,因此我們不會(huì)注意到任何性能影響。
但是總的來(lái)說(shuō),運(yùn)行時(shí)的求值的數(shù)量越少,性能就越好。
// maxWidth - (margin * 2) const maxWidth = '980' // minWidth - (margin * 2) const minWidth = '80' const margin = '10' getWidth = () => ({ maxWidth, minWidth, })
使用 Map 而不是 switch/if-else 條件
如果要檢查多個(gè)條件時(shí),可以使用Map代替 switch/if-else條件。在Map中查找元素的性能比對(duì)switch和if-else條件快得多。
switch (day) { case 'monday': return 'workday' case 'tuesday': return 'workday' case 'wednesday': return 'workday' case 'thursday': return 'workday' case 'friday': return 'workday' case 'saturday': return 'funday' case 'sunday': return 'funday' } // or this if ( day === 'monday' || day === 'tuesday' || day === 'wednesday' || day === 'thursday' || day === 'friday' ) return 'workday' else return 'funday'
上面可以使用 Map 來(lái)代替
const m = new Map([ ['monday','workday'], ['tuesday', 'workday'], ['wednesday', 'workday'], ['thursday', 'workday'], ['friday', 'workday'], ['saturday', 'funday'], ['sunday', 'funday'] ]; return m.get(day);
if-else 排序
在 React組件中,這種寫法還是很常見(jiàn)的。
export default function UserList(props) { const { users } = props if (users.length) { return <UserList /> } return <EmptyUserList /> }
在這里,我們?cè)跊](méi)有用戶時(shí)渲染
export default function UserList(props) { const { users } = props if (!users.length) { return <EmptyUserList /> } // some resource intensive operation return <UserList /> }
當(dāng)然 users.length 一直有值的話,就使用第一種情況。
類型是你最好的朋友
JavaScript是解釋型和編譯型語(yǔ)言。為了產(chǎn)生更有效的二進(jìn)制文件,編譯器需要類型信息。但是,作為一種動(dòng)態(tài)類型化的語(yǔ)言會(huì)使編譯器難以進(jìn)行。
編譯器在編譯熱代碼(多次執(zhí)行的代碼)時(shí)進(jìn)行一些假設(shè)并優(yōu)化代碼。編譯器花費(fèi)一些時(shí)間來(lái)生成此優(yōu)化的代碼。當(dāng)這些假設(shè)失敗時(shí),編譯器必須丟棄優(yōu)化的代碼,并退回到解釋的執(zhí)行方式。這是耗時(shí)且昂貴的。
看完上述內(nèi)容,你們掌握J(rèn)avaScript優(yōu)化技巧都有哪些的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。