この翻訳は不完全です。英語から この記事を翻訳 してください。

map() メソッドは、与えられた関数を配列のすべての要素に対して呼び出し、その結果からなる新しい配列を生成します。

構文

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

引数

callback
新しい配列の要素を生成するための関数。次の3つ引数を取る。
 
currentValue
現在処理中の要素の値。
indexOptional
現在処理中の要素の配列内におけるインデックス。
arrayOptional
map が実行されている配列。
thisArgOptional
callback を実行するときに this として使用するオブジェクト。

戻り値

与えられた関数を配列のすべての要素に対して呼び出し、その結果からなる新しい配列。

説明

map は、与えられた callback 関数を配列の順番通りに、各要素に対して一度ずつ呼び出し、その結果から新しい配列を生成します。callback は、値が代入されている配列のインデックスに対してのみ呼び出されます(undefined が代入されているものも含みます)。すでに削除されたインデックスや、まだ値が代入されていないインデックスに対しては呼び出されません。

callback は、要素の値、要素のインデックス、走査されている Array オブジェクトという 3 つの引数をともなって呼び出されます。

mapthisArg パラメーターが与えられると、callback の呼び出しのたびにそのオブジェクトが this として使用されます。パラメーターが省略された場合、this の値として undefined が渡されます。callback によって最終的に識別できる this の値は、関数における通常の this を決定するルールにしたかがって決まります。

map は呼び出された配列を変化させません。(ただし、呼び出された callback が配列を変化させている場合はこの限りではありません。)

map によって処理される要素の範囲は、callback が最初に呼び出される前に設定されます。map の呼び出しが開始された後に追加された要素に対しては、callback は実行されません。既存の配列要素が変更されたり、削除された場合、callback に渡される値は map がそれらを訪れた時点での値になり、map が削除された要素を訪問することはありません。

仕様書で定義されているアルゴリズムによって、map が呼び出された配列がまばらである場合、結果の配列も同じインデックスを空白に保ちます。

数値の配列を平方根の配列にマッピングする

次のコードは、数値からなる配列を取り、それらの数値の平方根からなる新しい配列を生成します。

var numbers = [1, 4, 9];
var roots = numbers.map(Math.sqrt);
// roots   の内容は [1, 2, 3] となる
// numbers の内容は [1, 4, 9] のまま

配列内のオブジェクトをフォーマットするために map を使用する

次のコードは、オブジェクトの配列を受け取り、新たにフォーマットされた新しい配列を生成しています。

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}]

引数を含む関数を使用して数値配列をマッピングする

次のコードは、1 つの引数を必要とする関数を使用するときに map がどのように動作するかを示しています。引数は元の配列を通した map ループとして、配列の各要素に自動的に割り当てられます。

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]

汎用的な map の使用

以下の例は、各文字を表す ASCII エンコードのバイトの配列を得るために String に map を使う方法を示しています。:

var map = Array.prototype.map;
var a = map.call('Hello World', function(x) { 
  return x.charCodeAt(0); 
});
// a の内容は [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. In this case we get all selected options on the screen and printed on the console:

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.

トリッキーな使用例

(このブログのポストにインスパイアされました)

コールバック関数は第一引数(変換するべき要素)だけを意識して指定するケースがほとんどだと思います。しかし一般的に第一引数しか使わないような関数でも、実は追加のオプション引数を受け取っている場合があります。これは混乱につながる可能性があります。

// このコードは...
['1', '2', '3'].map(parseInt);
// 戻り値は [1, 2, 3] となりそうですが、
// 実際には [1, NaN, NaN] となります。

// parseInt は大抵一つの引数のみで使われますが、実際には二つの引数を取っています。
// 一つ目は数値文字列、二つ目は基数です。
// Array.prototype.map はコールバックに次の3つの引数を与えています。
//   要素, インデックス, 配列
// parseInt は三つ目の引数を無視しますが、二つ目の引数は処理の対象とします。
// これがどんな混乱を引き起こすかは上記のブログを見て下さい。

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

['1', '2', '3'].map(returnInt); // [1, 2, 3]
// 期待した通り、数値の配列が返る。

// アロー関数構文を使って、より簡潔に上記と同じ結果を得ることが出来ます。
['1', '2', '3'].map( str => parseInt(str) );

// ちなみにこの命題ではもっと簡単に同じ結果を得る方法があります。
['1', '2', '3'].map(Number); // [1, 2, 3]
// ただ、parseInt とは違って小数表現も解釈しますし、指数表現まで処理してしまいますけどね。
['1.1', '2.2e2', '3e300'].map(Number); // [1.1, 220, 3e+300]

ポリフィル

map は ECMA-262 標準に最近追加されたものである為、標準準拠を謳う実装中に存在しない場合があります。次のコードをスクリプトの先頭に挿入すると、map がネイティブでサポートされていない ECMA-262 実装でも map を使用できるようになります。このアルゴリズムは ECMA-262 第 5 版で指示されたアルゴリズムと全く同じものです。ObjectTypeErrorArray はそれぞれオリジナルの値を持ち、またそれらの 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;
  };
}

仕様

仕様 ステータス コメント
ECMAScript 5.1 (ECMA-262)
Array.prototype.map の定義
標準 初期定義。JavaScript 1.6 で実装。
ECMAScript 2015 (6th Edition, ECMA-262)
Array.prototype.map の定義
標準  
ECMAScript Latest Draft (ECMA-262)
Array.prototype.map の定義
ドラフト  

Browser compatibility

機能ChromeEdgeFirefoxInternet ExplorerOperaSafari
基本対応 あり あり1.59 あり あり
機能Android webviewChrome for AndroidEdge mobileFirefox for AndroidOpera AndroidiOS SafariSamsung Internet
基本対応 あり あり あり4 あり あり あり

関連項目

ドキュメントのタグと貢献者

 このページの貢献者: woodmix, mdmss37, YuichiNukiyama, teoli, tatsuyaoiw, ethertank, Potappo, Shoot
 最終更新者: woodmix,