[] .map.call()VS Array.prototype.map.call()?

时间:2016-02-24 20:41:48

标签: javascript arrays performance dictionary

为什么一个人比另一个更受欢迎?

w(y'+yx')

w(y'+x')

jsPerf中进行快速测试表明,Array.prototype方式更高效,尽管我在某处读到jsPerf结果可能是欺骗性的。不是在这里讨论jsPerf,而只是寻找一些有关为什么一个人比另一个更受欢迎的见解。谢谢!

2 个答案:

答案 0 :(得分:10)

[].mapArray.prototype.map的值(在没有恶作剧的情况下)相同。表达式[].map涉及(至少在概念上;它可以被优化掉)构造一个新的Array实例,因此可能具有(非常小的)性能影响。

表达式[].map创建一个新的空数组,然后引用其“map”属性。除非添加一个实例,否则数组实例没有“map”属性,因此在对象本身上找不到它。因此,运行时将检查原型链上的下一个事物,当然是Array.prototype对象。运行时在那里找到“map”属性 - 具体来说,Array.prototype.map。这就是为什么他们是同一件事。

类似的等价适用于{}.toStringObject.prototype.toString。使用模式的主要区别可能是{}.toString在表达式的最开头出现时会导致问题,因为在这种情况下,前导{将被视为语句块{{1 },而不是对象初始化{。但是,{的典型用法是,它不太可能需要启动表达式。因此

{}.toString

一样有效
console.log({}.toString.call(someMysteryObject));

在性能方面,在console.log(Object.prototype.toString.call(someMysteryObject)); 的情况下,在使用该方法时隐式的函数调用的开销几乎肯定会完全淹没两种查找{{{{ 1}}开始时的功能。

答案 1 :(得分:4)

基准

1。上下文

我做了一个基本的基准测试,看看我是否能发现这四种不同陈述之间在性能上的任何差异:

  • dataSet.map(function)
  • dataSet.map.call(dataSet, function)
  • [].map.call(dataSet, function)
  • Array.prototype.map.call(dataSet, function)

2。方法

我在隔离的沙箱中执行了1,000,000次四个语句中的每一个,然后比较了处理时间。

我使用以下计时器功能来确定处理时间:

var timer = function(name) {
    var start = new Date();
    return {
        stop: function() {
            var end  = new Date();
            var time = end.getTime() - start.getTime();
            console.log('Timer:', name, 'finished in', time, 'ms');
        }
    }
};

3。测试环境

我在配备Intel i7四核CPU的2年前华硕笔记本电脑上进行测试。

我在Linux Ubuntu上测试了以下两种浏览器:

  • Firefox 43.0
  • Chrome 45.0

4。方案

4.1。 dataSet.map(function)

的情景
var t = timer('Benchmark'); // <-- START BENCHMARK

var reformattedArray;
var rObj;
var kvArray = [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}];
for(var i = 0; i < 1000000; i++) {
    reformattedArray = kvArray.map(function(obj){ 
        rObj = {};
        rObj[obj.key] = obj.value;
        return rObj;
    });
}

t.stop();  // <-- STOP BENCHMARK

(另见this Fiddle

4.2。 dataSet.map.call(dataSet, function)

的情景
var t = timer('Benchmark'); // <-- START BENCHMARK

var reformattedArray;
var rObj;
var kvArray = [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}];
for(var i = 0; i < 1000000; i++) {
    reformattedArray = kvArray.map.call(kvArray, function(obj){
        rObj = {};
        rObj[obj.key] = obj.value;
        return rObj;
    });
}

t.stop();  // <-- STOP BENCHMARK

(另见this Fiddle

4.3。 [].map.call(dataSet, function)

的情景
var t = timer('Benchmark'); // <-- START BENCHMARK

var reformattedArray;
var rObj;
var kvArray = [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}];
for(var i = 0; i < 1000000; i++) {
    reformattedArray = [].map.call(kvArray, function(obj){
        rObj = {};
        rObj[obj.key] = obj.value;
        return rObj;
    });
}

t.stop();  // <-- STOP BENCHMARK

(另见this Fiddle

4.4。 Array.prototype.map.call(dataSet, function)

的情景
var t = timer('Benchmark'); // <-- START BENCHMARK

var reformattedArray;
var rObj;
var kvArray = [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}];
for(var i = 0; i < 1000000; i++) {
    reformattedArray = Array.prototype.map.call(kvArray, function(obj){
        rObj = {};
        rObj[obj.key] = obj.value;
        return rObj;
    });
}

t.stop();  // <-- STOP BENCHMARK

(另见this Fiddle

5。中级结果

我没有发现四种情况之间存在任何性能差异,但我确实注意到Firefox的速度比Chrome快4倍(对于这两种情况)。

更具体地说,处理每个场景需要大约1秒的时间,而Fixefox仅需0.25秒。

为了评估这些浏览器差异是否特定于map方法,我进一步简化了测试。

6。情景v2

6.1。 dataSet.map(function)

的场景v2
var t = timer('Benchmark'); // <-- START BENCHMARK

var reformattedArray;
var rObj;
var kvArray = [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}];
for(var i = 0; i < 1000000; i++) {
    kvArray.map(function(obj){ 
        return rObj;
    });
}

t.stop(); // <-- STOP BENCHMARK

(另见this Fiddle

6.2。 dataSet.map.call(dataSet, function)

的场景v2
var t = timer('Benchmark'); // <-- START BENCHMARK

var reformattedArray;
var rObj;
var kvArray = [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}];
for(var i = 0; i < 1000000; i++) {
    kvArray.map.call(kvArray, function(obj){
        return rObj;
    });
}

t.stop(); // <-- STOP BENCHMARK

(另见this Fiddle

6.3。 [].map.call(dataSet, function)

的场景v2
var t = timer('Benchmark'); // <-- START BENCHMARK

var reformattedArray;
var rObj;
var kvArray = [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}];
for(var i = 0; i < 1000000; i++) {
    [].map.call(kvArray, function(obj){
        return rObj;
    });
}

t.stop(); // <-- STOP BENCHMARK

(另见this Fiddle

6.4。 Array.prototype.map.call(dataSet, function)

的场景v2
var t = timer('Benchmark'); // <-- START BENCHMARK

var reformattedArray;
var rObj;
var kvArray = [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}];
for(var i = 0; i < 1000000; i++) {
    Array.prototype.map.call(kvArray, function(obj){
        return rObj;
    });
}

t.stop(); // <-- STOP BENCHMARK

(另见this Fiddle

7。最终结果

现在,Chrome运行这些方案大约需要0.275秒,Firefox需要大约0.035秒。这意味着Firefox的速度比Chrome快了7倍。

同样,使用相同浏览器时,四种方案中的每种方案之间的性能没有明显差异。