4

According to a JSPerf snippet (and some others), default JavaScript map() implementation is 21% slower than using a basic for.

enter image description here

Looking at the official polyfill, I immediately understand why map() is that slow.

Polyfill strange part

line 15: var O = Object(this);

Initial object is converted (and duplicated) in a JavaScript object.

line 42: while (k < len) {

Right, starting from 0, it iterates over the full array length, seems legit!

line 52: if (k in O) {

That's the point. This check is so slow and is repeated for each operation. The in operation may use a sequential search in the array, which is that slow and affects global performances.

Iterating over an array from 0 to array.length doesn't imply to check, each time, whether the index does exist.

Why is this check useful?

  • It seems to me that this is a pretty direct translation of the algorithm in the specification, IOW, the algorithm it must execute. You are allowed to change the algorithm, of course, or make optimizations, provided that you do always, under any possible circumstance return the same result as the algorithm in the spec. Do you see any obvious improvements? – Jörg W Mittag Apr 13 '17 at 14:43
  • @JörgWMittag Thanks for this clarification! I guess most developers use map() function on arrays most of the time, so an improvement could be to create a dedicated amap() function (for array map) which does the same treatment but without the double-check, so that performances are not affected, what do you think? – sweepy_ Apr 13 '17 at 15:07
  • I think we could hide the slow 'in' test behind 'undefined' for big speedup except on very sparse arrays. if (O[k]!==undefined || k in O) – strainer Jun 21 '17 at 13:23
6

An array is still an Object, so you can delete it keys. For example:

var x = [0,1,2,3,4];
delete x[2];
x.map(function (x) { return x + 10; });

The property with the key '2' is no longer defined. For Arrays that means there is an empty slot.

The specification also allows you to modify the array you map over during mapping:

The range of elements processed by map is set before the first call to callbackfn . Elements which are appended to the array after the call to map begins will not be visited by callbackfn . If existing elements of the array are changed, their value as passed to callbackfn will be the value at the time map visits them; elements that are deleted after the call to map begins and before being visited are not visited.

The specification for map also ends with following comment on the map function, which may offer further explanation for the rationale:

The map function is intentionally generic; it does not require that its this value be an Array object. Therefore it can be transferred to other kinds of objects for use as a method. Whether the map function can be applied successfully to a host object is implementation-dependent.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.