Array.map的Javascript性能

时间:2014-03-04 20:35:42

标签: javascript performance jsperf

刚刚在jsperf中编写了一些测试用例,以便在使用Array.map和其他替代方法时测试命名函数和匿名函数之间的区别。

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

(请注意网址名称,此处没有Array.reduce的测试,我在完全决定要测试的内容之前命名了测试)

一个简单的for / while循环显然是最快的,但我仍然感到惊讶的是Array.map慢了10倍......

然后我尝试了mozilla https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map#Polyfill

的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. 简单/ while(大约相同)
  2. Map3(我自己的实现)
  3. Map2(Mozilla polyfill)
  4. Array.map
  5. for in
  6. 观察

    一个有趣的注意事项是,命名函数通常比使用匿名函数(大约5%)快得多。但是我注意到polyfill在firefox中的命名函数速度较慢,但​​在chrome中速度较快,但是chrome的自己的map实现在命名函数中较慢...我测试了这个函数大约10x,所以即使它不是完全密集测试(jsperf)已经这样做了,除非我的运气好,它应该足够作为指导。

    此外,chrome的map功能比我机器上的firefox慢2倍。完全没想到。

    而且...... firefox自己的Array.map实现比Mozilla Polyfill慢......哈哈

    我不确定为什么ECMA-262规范声明map可以用于阵列以外的对象(http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.19)。这使整个地图的功能慢了3-4倍(如我的测试所示),因为你需要检查每个循环的属性是否存在......

    结论

    如果您认为不同的浏览器的执行方式略有不同,则命名函数和匿名函数之间没有太大区别。

    在一天结束时,我们不应该真正微观优化,但我发现这很有趣:)

1 个答案:

答案 0 :(得分:2)

首先,这不是一个公平的比较。如你所说,正确的javascript地图能够使用对象,而不仅仅是数组。因此,您基本上将两个完全不同的函数与不同的算法/结果/内部工作进行比较。

当然正确的javascript地图速度较慢 - 它的设计目的是在一个更大的域上工作而不是在一个简单的数组上工作。