【譯】JavaScript 中的性能和可讀性

原文:Performance vs Readability算法

JavaScript 已經發展成爲一種更易讀的語言。毫無疑問,這對這門語言的發展是毫無害處的。數組

而軟件開發始終是在一個團隊不斷變化的動態環境中的,這意味着現有代碼對於團隊新手來講是須要可讀的。可是,可讀性必須是以性能爲代價的嗎?在哪裏劃分性能和可讀性之間的界限?何時犧牲一個來追求另外一個?是否須要在某些時候犧牲其中一個?瀏覽器

在下面,筆者準備回答上述的一些問題?或者幫你們試圖一塊兒去理解。服務器

還有一個問題是,你們嘗試在代碼中實現高性能的緣由是顯而易見的,可是,爲何也如此沉迷於可讀性呢?函數

一樣的問題,不一樣的解決方案

下面,咱們來看一個很常見的問題:工具

給定一組無序數字,返回一個新數組,爲每一個值加 1 並對其進行排序,同時不改變原始數組的數據。oop

var numbers = [2, 4, 12, 6, 8, 29, 5, 10, 87, 11, 7];性能

function process(arr) { let newArr = arr.slice(); newArr[0]++; for (let i = 1; i < newArr.length; i++) { const current = newArr[i] + 1; let leftIndex = i - 1;測試

while (leftIndex >= 0 && newArr[leftIndex] > current) {
        newArr[leftIndex + 1] = newArr[leftIndex];
        leftIndex = leftIndex - 1;
    }
    newArr[leftIndex + 1] = current;
}
return newArr;
複製代碼

}大數據

const newArray = process(numbers);

(筆者使用插入排序,只是由於它比較容易實現)

這個代碼示例並非真正可讀的,可是,性能更高,比可讀的 ES6 代碼更高效。例如這個:

const process = (arr) => arr .map(num => num + 1) .sort((a, b) => a - b);

const newArray = process(numbers);

事實上,第一個代碼示例比第二個代碼示例快約 75%,即便第二個代碼示例更具可讀性,甚至能夠簡化爲單行代碼:

const newArray = numbers.map(num => num + 1).sort((a, b) => a - b);

或者使用輔助函數拆分以得到更好的可讀性:

const addOne = (n) => n + 1; const asc = (a, b) => a - b; const newArray = numbers.map(addOne).sort(asc);

很明顯,ES6 示例(不管採用何種方法)都更具可讀性,使代碼更容易理解。 採用可讀代碼,團隊能夠更快地向項目中引入新的開發人員,也能夠更輕鬆地共享代碼,並使其更易於維護。

考慮到所有因素,在大多數狀況下,性能變得並不是那麼重要。這就是 ES6 以這種方式發展的緣由。

兩種方法之間的最終比較:

在這一點上,你可能會問:「還有什麼不那麼高效,但更具可讀性的代碼?

好吧,下面讓咱們一塊兒看看一些主要的用例。

Spread 語法 vs Object.assign()

來看下面這個簡單問題:

複製對象並向副本添加新屬性

解決方案:

const params = {...}; // filled Object

// ES6 - Spread syntax var copy1 = { a: 2, ...params };

// Object.assign() var copy2 = Object.assign({}, { a: 2 }, params);

這兩種方法均可以完成這項工做,但** Spread 語法更易讀,即便速度慢約 54%**。

關於循環和 Reduce

問題:

求和數組的全部值

解決方案,從經典的 for ... loop 開始:

const numbers = [2, 4, 12, 6, 8, 29, 5, 10, 87, 11, 7];

function arraySum(arr) { let sum = 0; for (let i = 0; i < arr.length; i++) { sum += arr[i] } return sum; }

const sumOfNumbers = arraySum(numbers);

如今使用 Reduce:

const numbers = [2, 4, 12, 6, 8, 29, 5, 10, 87, 11, 7];

const add = (a, b) => a + b; const arraySum = (arr) => arr.reduce(add);

const sumOfNumbers = arraySum(numbers);

在這種狀況下,從性能的角度來看,下降是很是明顯的,速度要慢約 96%!

For vs While vs Do while

差別很是不明顯,可是,若是非要有結論的話,請繼續使用經典的 for 循環。

何時用什麼

哇! 如今不少可讀性的編碼方式很受歡迎。筆者正在使用 spread 語法,reduce 等等來完成全部邏輯!

這裏的情緒有點使人沮喪,他們承諾可讀性而沒有性能成本的!但事實並不是如此。

這裏不要惶恐不安,來分析下當前的狀況。 那麼,「我何時用?

上述問題的答案比實際預期的要容易:取決於項目狀況

回到第一個例子,若是必須:複製,添加和排序中小數據量的數組或對象,那麼爲了可讀性,咱們將使用 ES6 武器庫中的全部可用玩具。

事實上,幾乎全部代碼均可以在編寫時將重點放在可讀性而不是性能上,但具體執行要取決於項目狀況。

咱們試着把這些狀況放在列表中來展現。

什麼時候優先考慮可讀性

  • 當咱們處理的數據量不是很大時
  • 當應用程序在速度,負載等方面正確運行時
  • 在具備許多項目新手的動態環境中工做時
  • 在編寫人們可能必須閱讀和理解的庫或插件時

什麼時候優先考慮性能

  • 在處理大數據時
  • 當應用程序運行緩慢或存在其餘性能問題時
  • 當項目意圖可擴展時
  • 在我的項目中工做時,可使用本身想要的高性能代碼

所以,若是咱們處理大數據,請避免在專門處理該對象或數組的代碼部分中使用 reduce,filter,map,spread 語法等。

結論

咱們應該退後一步來看,分析選選擇的方式是否讓項目和用例變得更方便,而不是伏先選擇最新和最酷的東西。

毫無疑問,新的 ES6 功能是讓人幸福的,在平常JavaScript 編碼中產生不少樂趣,但若是正在努力提升性能,或者處理大量數據,這對應該從新考慮正在使用的那些工具。

對於繁重的工做,筆者會尋求一個不太可讀的代碼,但性能更高。💪

對於大量數據,筆者會去研究和實現最適合該任務的高性能算法。 💪👓

對於全部其餘狀況,筆者選擇了 ES6 這個可讀的小可愛 !!❤

聲明

在不一樣的瀏覽器、操做系統和服務器工做負載的情形下,此帖子中顯示的測試結果可能略有不一樣。

相關文章
相關標籤/搜索