最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - [].map.call() VS Array.prototype.map.call()? - Stack Overflow

programmeradmin2浏览0评论

Why would one be preferred over the other?

[].map.call(...)

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

Doing a quick test in jsPerf shows the Array.prototype way is more performant, although I read somewhere that jsPerf results can be deceiving. Not here to debate jsPerf, rather, just looking for some insight on why one would be preferred over the other. Thanks!

Why would one be preferred over the other?

[].map.call(...)

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

Doing a quick test in jsPerf shows the Array.prototype way is more performant, although I read somewhere that jsPerf results can be deceiving. Not here to debate jsPerf, rather, just looking for some insight on why one would be preferred over the other. Thanks!

Share Improve this question asked Feb 24, 2016 at 20:41 The QodesmithThe Qodesmith 3,3755 gold badges33 silver badges45 bronze badges 3
  • 2 They are exactly the same – adeneo Commented Feb 24, 2016 at 20:42
  • This has probably something to do about the JS optimizer. I expect the results should vary quite a bit on different browsers. – Vilx- Commented Feb 24, 2016 at 20:45
  • By the way, the results on my puter are quite identical for both approaches, using both IE11 and Chrome. The cumulative results also now show the same. The lesson here is - when doing statistics, you need a lot of samples, otherwise the results can get skewed VERY easily. Like it just happened. :) – Vilx- Commented Feb 24, 2016 at 20:49
Add a ment  | 

2 Answers 2

Reset to default 13

The values of [].map and Array.prototype.map are (in the absence of shenanigans) identical. The expression [].map involves (at least conceptually; it could be optimized away possibly) the construction of a new Array instance, so that could have (extremely minor) performance implications.

The expression [].map creates a new empty array, and then references its "map" property. Array instances don't have a "map" property unless you add one, so it won't be found on the object itself. The runtime will therefore check the next thing on the prototype chain, which is of course the Array.prototype object. The runtime will find a "map" property there — specifically, Array.prototype.map. That's why they're the same thing.

An analogous equivalence holds for {}.toString and Object.prototype.toString. The main difference in usage patterns may be that {}.toString can cause issues when it appears at the very beginning of an expression, because the leading { in that case will be taken to be a statement block {, not an object initialization {. However, typical uses of {}.toString are such that it's not terribly likely that it'd need to start an expression. Thus

console.log({}.toString.call(someMysteryObject));

works just as well as

console.log(Object.prototype.toString.call(someMysteryObject));

Performance-wise, in the case of .map(), the overhead of the function calls implicit in the use of that method will almost certainly pletely overwhelm the performance difference between the two ways of finding a reference to the .map() function at the start.

Benchmarking

1. Context

I did a basic benchmark test to see if I could spot any differences in performance between these four different statements :

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

2. Method

I executed each of the four statements 1,000,000 times in an isolated sandbox and pared processing time afterwards.

I used the following timer function to determine processing time :

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. Test environment

I ran my tests on a 2-year-old ASUS laptop with an Intel i7 quad-core CPU.

I tested in Linux Ubuntu, on the following two browsers :

  • Firefox 43.0
  • Chrome 45.0

4. Scenarios

4.1. Scenario for 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

(see also this Fiddle)

4.2. Scenario for 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

(see also this Fiddle)

4.3. Scenario for [].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

(see also this Fiddle)

4.4. Scenario for 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

(see also this Fiddle)


5. Intermediate results

I did not notice any performance difference between each of the four scenarios, however I did notice that Firefox was about 4x faster than Chrome (for both scenarios).

To be more specific, it takes Chrome about 1 seconds to process each scenario, whereas it takes Fixefox only 0.25 seconds.

To assess whether these browser differences are specific to the map method, I simplified the tests even further.


6. Scenarios v2

6.1. Scenario v2 for 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++) {
    kvArray.map(function(obj){ 
        return rObj;
    });
}

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

(see also this Fiddle)

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

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

(see also this Fiddle)

6.3. Scenario v2 for [].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

(see also this Fiddle)

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

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

(see also this Fiddle)


7. Final results

Now, Chrome takes about 0.275 seconds to run these scenarios, and Firefox takes about 0.035 seconds. That means Firefox is more than 7x faster than Chrome, here.

Again, there's no noticeable difference in performance between each of the four scenarios when using the same browser.

发布评论

评论列表(0)

  1. 暂无评论