Array.prototype.map()

De map() methode maakt een nieuwe array aan met als inhoud het resultaat van het aanroepen van de meegegeven functie op elk van de elementen uit de originele array.

Syntax

var new_array = arr.map(function callback(currentValue[, index[, array]]) {
    // Return element for new_array
}[, thisArg])

Parameters

callback
Functie die een element voor de nieuwe Array produceert en de volgende argumenten aanvaardt:
currentValue
Het huidige te verwerken element uit de array.
indexOptional
De index van het huidige te verwerken element in die array.
arrayOptional
De array waarop map werd opgeroepen.
thisArgOptional
Waarde die moet gebruikt worden voor this bij het uitvoeren van callback.

Return value

Een nieuwe array waarbij elk element het resultaat is van het oproepen van de functie op het overeenkomstige element uit de originele array.

Beschrijving

map roept de meegegeven callback functie één keer op voor elk element in een array, in volgorde, en maakt een nieuwe array met de resultaten. callback wordt enkel opgeroepen voor indices van de array die een waarde hebben, inclusief undefined. Het wordt niet opgeroepen voor element die niet (meer) in de array zitten (indices die nog nooit gezet zijn, die werden verwijderd of die nog nooit een waarde hebben gekregen).

Aangezien map een nieuwe array aanmaakt, heeft het geen zin deze methode aan te roepen als je de geretourneerde array niet gebruikt; gebruik dan eerder forEach of for-of. Gebruik map niet als: A) je de geretourneerde array niet gebruikt, en/of B) de callback functie geen waarde retourneert.

callback wordt aangeroepen met drie argumenten: de waarde van het element, de index van het element en het Array object zelf dat wordt doorlopen.

Als een thisArg parameter wordt meegegeven aan map, zal het gebruikt worden als this waarde voor de callback functie. Indien niet, wordt undefined gebruikt als zijn this waarde. De this waarde zoals callback ze uiteindelijk waarneemt, wordt bepaald volgens de gewone regels voor het bepalen van this zoals waargenomen door een functie.

map wijzigt de array waarop het wordt aangeroepen niet (ofschoon callback, indien aangeroepen, dat wél kan doen).

Het aantal elementen dat wordt verwerkt door map wordt bepaald vooraleer de eerste aanroep van callback plaatsvindt. Elementen die worden toegevoegd aan de array nadat de aanroep van map is gebeurd zullen door callback niet worden behandeld. Als bestaande elementen van de array worden gewijzigd, dan zijn de waarden die worden doorgegeven aan callback de waarden op het moment dat map ze beschouwt. Elementen die worden verwijderd na het aanroepen van map en vóór ze werden beschouwd worden niet verwerkt.

Voor de indices waarop de originele array lege plaatsen bevat, zal ook de resulterende array lege plaatsen bevatten.

Voorbeelden

Een array van getallen mappen op een array van vierkantswortels

De volgende code neemt een array van getallen en creëert een nieuwe array die de vierkantswortels van die getallen bevat.

var getallen = [1, 4, 9];
var vierkantsWortels = getallen.map(function(getal) {
return Math.sqrt(getal)
});
// vierkantsWortels is nu [1, 2, 3]
// getallen is nog steeds [1, 4, 9]

Gebruik van map om objecten te herformateren in een array

De volgende code neemt een array van objecten en creëert een nieuwe array die de geherformatteerde objecten bevat.

var kvArray = [{key: 1, value: 10}, 
               {key: 2, value: 20}, 
               {key: 3, value: 30}];

var reformattedArray = kvArray.map(obj =>{ 
   var rObj = {};
   rObj[obj.key] = obj.value;
   return rObj;
});
// reformattedArray is now [{1: 10}, {2: 20}, {3: 30}], 

// kvArray is still: 
// [{key: 1, value: 10}, 
//  {key: 2, value: 20}, 
//  {key: 3, value: 30}]

Mapping an array of numbers using a function containing an argument

The following code shows how map works when a function requiring one argument is used with it. The argument will automatically be assigned from each element of the array as map loops through the original array.

var numbers = [1, 4, 9];
var doubles = numbers.map(function(num) {
  return num * 2;
});

// doubles is now [2, 8, 18]
// numbers is still [1, 4, 9]

Using map generically

This example shows how to use map on a String to get an array of bytes in the ASCII encoding representing the character values:

var map = Array.prototype.map;
var a = map.call('Hello World', function(x) { 
  return x.charCodeAt(0); 
});
// a now equals [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]

Using map generically querySelectorAll

This example shows how to iterate through a collection of objects collected by querySelectorAll. This is because querySelectorAll returns a NodeList which is a collection of objects.
In this case we return all the selected options' values on the screen:

var elems = document.querySelectorAll('select option:checked');
var values = Array.prototype.map.call(elems, function(obj) {
  return obj.value;
});

Easier way would be using Array.from() method.

Tricky use case

(inspired by this blog post)

It is common to use the callback with one argument (the element being traversed). Certain functions are also commonly used with one argument, even though they take additional optional arguments. These habits may lead to confusing behaviors.

// Consider:
['1', '2', '3'].map(parseInt);
// While one could expect [1, 2, 3]
// The actual result is [1, NaN, NaN]

// parseInt is often used with one argument, but takes two.
// The first is an expression and the second is the radix.
// To the callback function, Array.prototype.map passes 3 arguments: 
// the element, the index, the array
// The third argument is ignored by parseInt, but not the second one,
// hence the possible confusion. See the blog post for more details
// If the link doesn't work
// here is concise example of the iteration steps:
// parseInt(string, radix) -> map(parseInt(value, index))
// first iteration (index is 0): parseInt('1', 0) // results in parseInt('1', 0) -> 1
// second iteration (index is 1): parseInt('2', 1) // results in parseInt('2', 1) -> NaN
// third iteration (index is 2): parseInt('3', 2) // results in parseInt('3', 2) -> NaN

function returnInt(element) {
  return parseInt(element, 10);
}

['1', '2', '3'].map(returnInt); // [1, 2, 3]
// Actual result is an array of numbers (as expected)

// Same as above, but using the concise arrow function syntax
['1', '2', '3'].map( str => parseInt(str) );

// A simpler way to achieve the above, while avoiding the "gotcha":
['1', '2', '3'].map(Number); // [1, 2, 3]
// but unlike `parseInt` will also return a float or (resolved) exponential notation:
['1.1', '2.2e2', '3e300'].map(Number); // [1.1, 220, 3e+300]

One alternative output of the map method being called with parseInt as a parameter runs as follows:

var xs = ['10', '10', '10'];

xs = xs.map(parseInt);

console.log(xs);
// Actual result of 10,NaN,2 may be unexpected based on the above description.

Polyfill

map was added to the ECMA-262 standard in the 5th edition; as such it may not be present in all implementations of the standard. You can work around this by inserting the following code at the beginning of your scripts, allowing use of map in implementations which do not natively support it. This algorithm is exactly the one specified in ECMA-262, 5th edition, assuming Object, TypeError, and Array have their original values and that callback.call evaluates to the original value of Function.prototype.call.

// Production steps of ECMA-262, Edition 5, 15.4.4.19
// Reference: http://es5.github.io/#x15.4.4.19
if (!Array.prototype.map) {

  Array.prototype.map = function(callback/*, thisArg*/) {

    var T, A, k;

    if (this == null) {
      throw new TypeError('this is null or not defined');
    }

    // 1. Let O be the result of calling ToObject passing the |this| 
    //    value as the argument.
    var O = Object(this);

    // 2. Let lenValue be the result of calling the Get internal 
    //    method of O with the argument "length".
    // 3. Let len be ToUint32(lenValue).
    var len = O.length >>> 0;

    // 4. If IsCallable(callback) is false, throw a TypeError exception.
    // See: http://es5.github.com/#x9.11
    if (typeof callback !== 'function') {
      throw new TypeError(callback + ' is not a function');
    }

    // 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
    if (arguments.length > 1) {
      T = arguments[1];
    }

    // 6. Let A be a new array created as if by the expression new Array(len) 
    //    where Array is the standard built-in constructor with that name and 
    //    len is the value of len.
    A = new Array(len);

    // 7. Let k be 0
    k = 0;

    // 8. Repeat, while k < len
    while (k < len) {

      var kValue, mappedValue;

      // a. Let Pk be ToString(k).
      //   This is implicit for LHS operands of the in operator
      // b. Let kPresent be the result of calling the HasProperty internal 
      //    method of O with argument Pk.
      //   This step can be combined with c
      // c. If kPresent is true, then
      if (k in O) {

        // i. Let kValue be the result of calling the Get internal 
        //    method of O with argument Pk.
        kValue = O[k];

        // ii. Let mappedValue be the result of calling the Call internal 
        //     method of callback with T as the this value and argument 
        //     list containing kValue, k, and O.
        mappedValue = callback.call(T, kValue, k, O);

        // iii. Call the DefineOwnProperty internal method of A with arguments
        // Pk, Property Descriptor
        // { Value: mappedValue,
        //   Writable: true,
        //   Enumerable: true,
        //   Configurable: true },
        // and false.

        // In browsers that support Object.defineProperty, use the following:
        // Object.defineProperty(A, k, {
        //   value: mappedValue,
        //   writable: true,
        //   enumerable: true,
        //   configurable: true
        // });

        // For best browser support, use the following:
        A[k] = mappedValue;
      }
      // d. Increase k by 1.
      k++;
    }

    // 9. return A
    return A;
  };
}

Specifications

Specification Status Comment
ECMAScript 5.1 (ECMA-262)
The definition of 'Array.prototype.map' in that specification.
Standard Initial definition. Implemented in JavaScript 1.6.
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'Array.prototype.map' in that specification.
Standard
ECMAScript Latest Draft (ECMA-262)
The definition of 'Array.prototype.map' in that specification.
Draft

Browser compatibility

Update compatibility data on GitHub
DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome voor AndroidFirefox voor AndroidOpera voor AndroidSafari op iOSSamsung InternetNode.js
mapChrome Volledige ondersteuning JaEdge Volledige ondersteuning 12Firefox Volledige ondersteuning 1.5IE Volledige ondersteuning 9Opera Volledige ondersteuning JaSafari Volledige ondersteuning JaWebView Android Volledige ondersteuning JaChrome Android Volledige ondersteuning JaFirefox Android Volledige ondersteuning 4Opera Android Volledige ondersteuning JaSafari iOS Volledige ondersteuning JaSamsung Internet Android Volledige ondersteuning Janodejs Volledige ondersteuning Ja

Legenda

Volledige ondersteuning  
Volledige ondersteuning

See also