首頁>技術>

作為開發人員,我們一直在尋找讓我們的程式碼更快更好的方法。但在此之前,編寫高效能程式碼需要做三件事:

瞭解語言及其工作原理基於用例進行設計除錯!修復!重複

記住這一點:任何傻瓜都可以編寫計算機可以理解的程式碼,優秀的程式設計師編寫人類可以

理解的程式碼。

我們來看看如何使 JavaScript程式碼執行得更快。

延遲

延遲演算法將計算延遲到需要執行時才執行,然後生成結果。

const someFn = () => {  doSomeOperation()  return () => {    doExpensiveOperation()  }}const t = someArray.filter((x) => checkSomeCondition(x)).map((x) => someFn(x))// 現在,如果有需要在執行t.map((x) => t())1234567891011

最快的程式碼是未執行的程式碼,所以儘量延遲執行。

JavaScript 使用原型繼承,JS 中所有物件都是Object的例項。

MDN說:嘗試訪問物件的屬性時,不僅會在物件上搜索該屬性,還會在物件的原型,原型的原型等上搜索該屬性,直到找到匹配屬性名或原型鏈的末端。

對於每個屬性,JavaScript引擎都必須遍歷整個物件鏈,直到找到匹配項。 如果使用不當,這會佔用大量資源,並影響應用程式的效能。

所以不要這樣:

const name = userResponse.data.user.firstname + userResponse.data.user.lastname1

而是這樣做:

const user = userResponse.data.userconst name = user.firstname + user.lastname12

使用臨時變數來儲存連結的屬性,而不是遍歷訪問整條鏈。

使用轉譯器之前要三思

在上述情況下,userResponse可能不是物件,如果是物件,它的屬性 user 也可能不是物件。所以,在獲取值時要進行檢查:

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    }  }}12345678910111213

這太囉嗦了。程式碼越多,bug 就越明顯。我們能把它縮小嗎?當然,可以使用 JS 中可選的連結、解構賦值來最佳化它。

const user = userResponse?.data?.userconst { firstname = '', lastname = ''} = userconst name = firstname + lastname123

是不是很靈活地,簡短? 不要使用這個要注意,Babel 會按照以下方式進行轉換:

'use strict'var _userResponse, _userResponse$datavar user =  (_userResponse = userResponse) === null || _userResponse === void 0    ? void 0    : (_userResponse$data = _userResponse.data) === null ||      _userResponse$data === void 0    ? void 0    : _userResponse$data.uservar _user$firstname = user.firstname,  firstname = _user$firstname === void 0 ? '' : _user$firstname,  _user$lastname = user.lastname,  lastname = _user$lastname === void 0 ? '' : _user$lastnamevar name = firstname + lastname12345678910111213141516

當使用轉譯時,確保你選擇了一個更適合你的用例的。

瞭解SMI和堆號

數字很​奇怪,ECMAScript將數字標準化為64位浮點值,也稱為雙精度浮點或Float64表示形式。

如果 JS 引擎以Float64表示形式儲存數字,則將導致巨大的效能低下。 JS 引擎對數字進行抽象,使其行為與Float64完全匹配。 與float64運算相比,JS 引擎執行整數運算的速度要快得多。

有時,我們認為像下面這樣寫法可讀比較好:

const maxWidth = '1000'const minWidth = '100'const margin = '10'getWidth = () => ({  maxWidth: maxWidth - margin * 2,  minWidth: minWidth - margin * 2,})1234567
評估區域性變數

如果getWidth函式被多次呼叫,那麼每次呼叫它時都會計算它的值。上面的計算並不是什麼大問題,因此我們不會注意到任何效能影響。

但是總的來說,執行時的求值的數量越少,效能就越好。

// maxWidth - (margin * 2)const maxWidth = '980'// minWidth - (margin * 2)const minWidth = '80'const margin = '10'getWidth = () => ({  maxWidth,  minWidth,})123456789
使用 Map 而不是 switch/if-else 條件

如果要檢查多個條件時,可以使用Map代替 switch/if-else條件。 在Map中查詢元素的效能比對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 thisif (  day === 'monday' ||  day === 'tuesday' ||  day === 'wednesday' ||  day === 'thursday' ||  day === 'friday')  return 'workday'else return 'funday'12345678910111213141516171819202122232425262728

上面可以使用 Map 來代替

const m = new Map([    ['monday','workday'],    ['tuesday', 'workday'],    ['wednesday', 'workday'],    ['thursday', 'workday'],    ['friday', 'workday'],    ['saturday', 'funday'],    ['sunday', 'funday']];return m.get(day);1234567891011
if-else 排序

在 React元件中,這種寫法還是很常見的。

export default function UserList(props) {  const { users } = props  if (users.length) {    return <UserList />  }  return <EmptyUserList />}123456789

在這裡,我們在沒有使用者時渲染<EmptyUserList />否則渲染<UserList />。 有大部分人認為,我們首先處理所有空的的情況,然後再處理有資料的情況。 對於任何讀過它的人來說都更清楚,而且效率更高。 也就是說,以下程式碼比上一個程式碼更有效。

export default function UserList(props) {  const { users } = props  if (!users.length) {    return <EmptyUserList />  }  // some resource intensive operation  return <UserList />}12345678910

當然 users.length 一直有值的話,就使用第一種情況。

型別是你最好的朋友

JavaScript是解釋型和編譯型語言。 為了產生更有效的二進位制檔案,編譯器需要型別資訊。 但是,作為一種動態型別化的語言會使編譯器難以進行。

編譯器在編譯熱程式碼(多次執行的程式碼)時進行一些假設並最佳化程式碼。 編譯器花費一些時間來生成此最佳化的程式碼。 當這些假設失敗時,編譯器必須丟棄最佳化的程式碼,並退回到解釋的執行方式。 這是耗時且昂貴的。

57
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 面試官:你瞭解樂觀鎖和悲觀鎖嗎?