.map()
map()メソッドは、配列の各要素での提供された関数を呼び出した結果を使用して、新しい配列を作成します。
文法
arr.map(callback[, thisArg])
| 引数 | 説明 |
|---|---|
| callback |
この関数は、3つの引数を取得して新しい配列の要素を生成します。 |
| thisArg |
callback実行時に、thisとして使用される値です。
|
説明
mapは提供されたcallback関数を配列の要素毎に順に呼び出し、
その結果から新しい配列を構築します。
callbackは、値が割り当てられているインデックスでのみ実行され、
削除された、または値が割り当てられたことがない未定義のインデックスでは実行されません。
callbackは、要素の値、要素のインデックス、現在巡っている配列オブジェクトとの、
3つの引数を使用して実行されます。
もし、thisArgパラメーターがmapへ提供された場合、
callbackが実行された際にそれが渡され、そのthis値として使用されます。
そうでなければ、undefined値がそのthis値として渡されます。
callbackによって最終的に供給されるthis値は、
関数によるthisの取り扱いの通常の規則に沿って決定されます。(翻訳に自信なし)
mapは、その呼出元の配列を変更しません。(callbackがそのような処理をするかもしれませんが)
mapによって処理される要素の範囲は、callbackの最初の呼び出しの直前に設定されます。
mapへの呼び出しが開始された後に追加された要素は、callbackの対象になりません。
もし変更または削除された配列の要素が存在する場合、
それらのコールバックへ渡された値はmapがそこへ到達した際の値となり、
要素が削除されていれば対象にはなりません。
例
例: 平方根の配列にマッピング
下記のコードは数値の配列を受け取り、その配列の平方根を含む新しい配列を作成します。
var numbers = [1, 4, 9];
var roots = numbers.map(Math.sqrt);
/*
rootsは、 [1, 2, 3]となります。
numbersは、[1, 4, 9]のままです。
*/
例: mapの一般的な使用
この例では、querySelectorAllによる、 オブジェクトの集合を通して繰り返し処理する方法を説明しています。 このケースでは画面上の全ての選択されたoptionを取得し、コンソールに出力しています。
[].map.call(document.querySelectorAll('select option:checked'), function(obj) {
console.log(obj.parentNode.id, obj.value);
})
使いづらいケース
(このブログ記事の内容に基づいたものです。)
コールバック関数に引数を一つ(巡っている要素)指定するのは一般的な方法です。 また、追加で任意の引数を取得するにも関わらず、 その関数は引数を1つだけ使用することを確実にすることが一般的です。 この慣習を守らないと、混乱を招く挙動につながる可能性があります。
// 次のような処理があるとします:
["1", "2", "3"].map(parseInt);
// [1, 2, 3]となることを期待しますが、
// [1, NaN, NaN]が実際の結果になります。
// parseIntは多くの場合、引数を1つだけ指定して使用されますが、
// 実際には引数を2つ受け取ることが出来ます。
// 2つ目の引数は基数(◯進数の◯にあたる部分)になります。
// 関数をコールバックするために、Array.prototype.mapに3つの引数が渡されます:
// 2つ目とは異なり、3つ目の引数はparseIntによって無視され、それが混乱の元になります。
// 詳細については、ブログの投稿を参照してください。
function returnInt(element){
return parseInt(element,10);
}
["1", "2", "3"].map(returnInt);
// 実際の結果は、(期待通りの)数値の配列になります。
Polyfill
mapは、5thエディションのECMA-262標準に追加されたため、
全ての標準実装に提供されていないかもしれません。
あなたのスクリプトが始まる前に下記のコードを挿入することで、
ネイティブにサポートされていない場合に、mapが使用出来るようになります。
このアルゴリズムは5thエディションのECMA-262標準の仕様と一致するもので、
Object、TypeError、Arrayはそれらの元の値、
callback.callはFunction.prototype.callの元の値を評価するものとみなします。(翻訳に自信なし)
// Production steps of ECMA-262, Edition 5, 15.4.4.19
// Reference: http://es5.github.com/#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 (thisArg) {
T = thisArg;
}
// 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) {
var Pk = k.toString(); // This was missing per item a. of the above comment block and was not working in IE8 as a result
// i. Let kValue be the result of calling the Get internal method of O with argument Pk.
kValue = O[Pk];
// 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, Pk, { value: mappedValue, writable: true, enumerable: true, configurable: true });
// For best browser support, use the following:
A[Pk] = mappedValue;
}
// d. Increase k by 1.
k++;
}
// 9. return A
return A;
};
}
仕様
ブラウザ互換性
| 機能 | Chrome | Firefox (Gecko) |
IE | Opera | Safari |
|---|---|---|---|---|---|
| 基本 | ◯ | 1.5 (1.8) | 9 | ◯ | ◯ |
| 機能 | Android | Chrome for Android |
Firefox Mobile |
IE Mobile |
Opera Mobile |
Safari Mobile |
|---|---|---|---|---|---|---|
| 基本 | ◯ | ◯ | 1.0 (1.8) | ◯ | ◯ | ◯ |
関連項目
© 2017 Mozilla Contributors
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
このページは、ページトップのURL先のMozilla Developer Network(以下、MDN)のコンテンツを翻訳した内容を基に構成されています。 構成について異なる点も含まれますので、下記の項目を確認し、必要に応じて元のコンテンツをご確認ください。 もし、誤訳などの間違いを見つけましたら、 @tomofまで教えていただければ幸いです。
- 特定のブラウザに特化しすぎている情報やあまりにも古い情報、 または試験的に導入されているようなAPIや機能については、省略していることがあります。
- 例やデモについて、実際にページ内で動作させる関係で一部ソースコードを変更している場合や、 その例で使用しているコンテンツの単語や文章などを日本人向けに変更しいてる場合があります。
- MDNの更新頻度が高いため、元のコンテンツと比べ情報が古くなっている可能性があります。
- "訳注:"などの断わりを入れた上で、日本人向けの情報の追記を行っている事があります。