2014-03-04 40 views
13

剛剛在jsperf中寫了一些測試用例來測試使用Array.map和其他替代方法時命名和匿名函數之間的區別。Array.map的Javascript性能

http://jsperf.com/map-reduce-named-functions

(原諒URL名稱,還有在這裏沒有Array.reduce測試,我命名之前完全決定什麼,我想測試試驗)

一個簡單的for/while循環是很明顯最快的,我仍然在10倍以上,慢Array.map雖然驚訝...

然後我由Mozilla嘗試填充工具https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map#Polyfill

Array.prototype.map = function(fun /*, thisArg */) 
{ 
    "use strict"; 

    if (this === void 0 || this === null) 
     throw new TypeError(); 

    var t = Object(this); 
    var len = t.length >>> 0; 
    if (typeof fun !== "function") 
     throw new TypeError(); 

    var res = new Array(len); 
    var thisArg = arguments.length >= 2 ? arguments[1] : void 0; 
    for (var i = 0; i < len; i++) 
    { 
     // NOTE: Absolute correctness would demand Object.defineProperty 
     //  be used. But this method is fairly new, and failure is 
     //  possible only if Object.prototype or Array.prototype 
     //  has a property |i| (very unlikely), so use a less-correct 
     //  but more portable alternative. 
     if (i in t) 
      res[i] = fun.call(thisArg, t[i], i, t); 
    } 

    return res; 
}; 

然後我嘗試一個簡單的實現,我寫我自己......

Array.prototype.map3 = function(callback /*, thisArg */) { 
    'use strict'; 
    if (typeof callback !== 'function') { 
     throw new TypeError(); 
    } 

    var thisArg = arguments.length >= 2 ? arguments[1] : void 0; 

    for (var i = 0, len = this.length; i < len; i++) { 
     this[i] = callback.call(thisArg, this[i], i, this); 
    }; 
}; 

摘要結果:

從最快到最慢:

  1. 對於簡單/時(約相同)
  2. Map3(我自己的實現)
  3. Map2(Moz利亞填充工具)
  4. Array.map

觀察

一個有趣的注意的是,命名函數通常是小有一點比如果您使用匿名函數(約5%)要快。但是我注意到firefil的命名函數的polyfill比較慢,但是在chrome中速度更快,但是chrome自己的map實現對於命名函數來說速度更慢......我測試了這個約10倍,所以即使它不是完全密集的測試(其中jsperf已經這樣做了),除非我的運氣很棒,它應該足以作爲指導。

此外,Chrome的map功能比我的機器上的Firefox慢2倍。沒有想到的是。

而且...... Firefox的自己Array.map實現比Mozilla的填充工具慢...哈哈

我不知道爲什麼ECMA-262規範指出map可用於除陣列其他對象(http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.19) 。這使得整個地圖功能慢3-4倍(如在我的測試中所示),因爲你需要檢查是否存在財產每次循環...

結論

之間有實在太大差別不是命名和匿名函數,如果你認爲不同的瀏覽器執行略有不同。

在一天結束的時候,我們真的不應該微觀優化太多,但我發現這個有趣的:)

+1

「有趣的是,命名函數通常比使用匿名函數的速度快得多」---當然。該代碼多次創建匿名函數。所以你的性能測試是不正確的,因爲他們有一些額外的噪音。 – zerkms

+0

@zerkms我的測試實際上得不到任何簡單的<_ <噪聲從哪裏來? – Populus

+1

http://jsperf.com/map-reduce-named-functions/2 - 這是一個更好的測試。 – zerkms

回答

1

那麼首先,這不是一個公平的比較。正如你所說,正確的JavaScript映射能夠使用對象,而不僅僅是數組。所以你基本上將兩種完全不同的功能與不同的算法/結果/內部工作進行比較。

當然,正確的JavaScript映射比較慢 - 它被設計爲在一個更大的域上工作,而不是一個簡單的數組。

+8

這是更多的評論比答案 – Gent

+7

@Gent,沒有問題... – xeon48