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

The*_*ith 1 javascript arrays performance dictionary

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

[].map.call(...)

Array.prototype.map.call(...)

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

Poi*_*nty 10

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

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

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

console.log({}.toString.call(someMysteryObject));
Run Code Online (Sandbox Code Playgroud)

同样有效

console.log(Object.prototype.toString.call(someMysteryObject));
Run Code Online (Sandbox Code Playgroud)

在性能方面,在.map()使用该方法时隐含的函数调用的开销几乎肯定会完全压倒.map()在开始时查找函数引用的两种方式之间的性能差异.


Joh*_*ers 5

标杆管理

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');
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

3、测试环境

我在一台使用了 2 年、配备 Intel i7 四核 CPU 的华硕笔记本电脑上进行了测试。

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

  • 火狐43.0
  • 铬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
Run Code Online (Sandbox Code Playgroud)

(另见这个小提琴

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
Run Code Online (Sandbox Code Playgroud)

(另见这个小提琴

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
Run Code Online (Sandbox Code Playgroud)

(另见这个小提琴

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
Run Code Online (Sandbox Code Playgroud)

(另见这个小提琴


5. 中间结果

我没有注意到这四种场景之间有任何性能差异,但我确实注意到 Firefox 比 Chrome 快大约 4 倍(对于这两种场景)。

更具体地说,Chrome处理每个场景大约需要1秒,而Fixefox只需要0.25秒。

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


6.场景v2

6.1. 场景 v2dataSet.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++) {
    kvArray.map(function(obj){ 
        return rObj;
    });
}

t.stop(); // <-- STOP BENCHMARK
Run Code Online (Sandbox Code Playgroud)

(另见这个小提琴

6.2. 场景 v2dataSet.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++) {
    kvArray.map.call(kvArray, function(obj){
        return rObj;
    });
}

t.stop(); // <-- STOP BENCHMARK
Run Code Online (Sandbox Code Playgroud)

(另见这个小提琴

6.3. 场景 v2[].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++) {
    [].map.call(kvArray, function(obj){
        return rObj;
    });
}

t.stop(); // <-- STOP BENCHMARK
Run Code Online (Sandbox Code Playgroud)

(另见这个小提琴

6.4. 场景 v2Array.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++) {
    Array.prototype.map.call(kvArray, function(obj){
        return rObj;
    });
}

t.stop(); // <-- STOP BENCHMARK
Run Code Online (Sandbox Code Playgroud)

(另见这个小提琴


7. 最终结果

现在,Chrome 大约需要 0.275 秒来运行这些场景,而 Firefox 大约需要 0.035 秒。这意味着 Firefox 的速度比 Chrome 快 7 倍以上。

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