1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
|
---
title: Array.prototype.map()
slug: Web/JavaScript/Reference/Global_Objects/Array/map
tags:
- Array
- ECMAScript 5
- JavaScript
- Method
- Prototype
- Reference
- polyfill
translation_of: Web/JavaScript/Reference/Global_Objects/Array/map
---
<div>{{JSRef}}</div>
<p><span class="seoSummary"><code><strong>map()</strong></code> メソッドは、与えられた関数を配列のすべての要素に対して呼び出し、その結果からなる<strong>新しい配列を生成します</strong>。</span></p>
<div>{{EmbedInteractiveExample("pages/js/array-map.html")}}</div>
<div class="hidden">このデモのソースファイルは GitHub リポジトリに格納されています。デモプロジェクトに協力したい場合は、 <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> をクローンしてプルリクエストを送信してください。</div>
<h2 id="Syntax" name="Syntax">構文</h2>
<pre class="syntaxbox notranslate">let <var>new_array</var> = <var>arr</var>.map(function <var>callback</var>( <var>currentValue</var>[, <var>index</var>[, <var>array</var>]]) {
// 新しい配列の要素を返す
}[, <var>thisArg</var>])
</pre>
<h3 id="Parameters" name="Parameters">引数</h3>
<dl>
<dt><code><var>callback</var></code></dt>
<dd>
<p><code><var>arr</var></code> の要素ごとに呼び出される関数です。 <code><var>callback</var></code> が実行されるたびに、返された値が <code><var>new_array</var></code> に追加されます。</p>
<p><code><var>callback</var></code> 関数は以下の引数を受け付けます。</p>
<dl>
<dt><code><var>currentValue</var></code></dt>
<dd>現在処理中の要素の値です。</dd>
<dt><code><var>index</var></code>{{optional_inline}}</dt>
<dd>現在処理中の要素の配列内における添字です。</dd>
<dt><code><var>array</var></code>{{optional_inline}}</dt>
<dd><code>map</code> が実行されている配列です。</dd>
</dl>
</dd>
<dt><code>thisArg</code>{{optional_inline}}</dt>
<dd><code><var>callback</var></code> を実行するときに <code>this</code> として使う値です。</dd>
</dl>
<h3 id="Return_value" name="Return_value">返値</h3>
<p>与えられた関数を配列のすべての要素に対して呼び出し、その結果からなる新しい配列です。</p>
<h2 id="Description" name="Description">解説</h2>
<p><code>map</code> は、与えられた <code><var>callback</var></code> 関数を配列の順番通りに、<strong>各要素に対して一度ずつ呼び出し</strong>、その結果から新しい配列を生成します。 <code><var>callback</var></code> は、値が代入されている配列の要素に対してのみ呼び出されます ({{jsxref("undefined")}} が代入されているものも含みます)。</p>
<p>これは配列の中で存在しない要素、すなわち以下の要素に対しては呼び出し<em>ません</em>。</p>
<ul>
<li>設定されたことがない添字</li>
<li>削除された要素</li>
<li>値を割り当てられたことがない要素</li>
</ul>
<h3 id="When_not_to_use_map" name="When_not_to_use_map">map() を使用すべきではない場合</h3>
<p><code>map</code> は新しい配列を作成するので、返された配列を使わない場合、map を使うのはパターンに合いません。代わりに {{jsxref("Array/forEach", "forEach")}} または {{jsxref("for...of", "for-of")}} を使用してください。</p>
<p><code>map</code> を使用するべきでないのは以下の場合です。</p>
<ul>
<li>返された配列を使用しない場合</li>
<li>コールバックから値を返さない場合</li>
</ul>
<h3 id="Parameters_in_Detail" name="Parameters_in_Detail">引数の詳細</h3>
<p><code><var>callback</var></code> は、要素の値、要素の添字、走査されている Array オブジェクトという 3 つの引数をともなって呼び出されます。</p>
<p><code>thisArg</code> 引数が与えられた場合は、それがコールバックの <code>this</code> として使用されます。引数が省略された場合は、 {{jsxref("undefined")}} が <code>this</code> の値として使用されます。 <code><var>callback</var></code> によって最終的に識別できる <code>this</code> の値は、<a href="/ja/docs/Web/JavaScript/Reference/Operators/this">関数における通常の <code>this</code> を決定するルール</a>に従って決まります。</p>
<p><code>map</code> は呼び出された配列を変化させません (ただし、呼び出された <code><var>callback</var></code> が配列を変更する可能性はあります)。</p>
<p><code>map</code> によって処理される要素の範囲は、 <code><var>callback</var></code> が最初に呼び出される前に設定されます。 <code>map</code> の呼び出しが開始された後に追加された要素に対しては、 <code><var>callback</var></code> は実行されません。既存の配列要素が変更されたり、削除された場合、 <code><var>callback</var></code> に渡される値は <code>map</code> がそれらを訪れた時点での値になり、 <code>map</code> が削除された要素を訪問することはありません。</p>
<p>仕様書で定義されているアルゴリズムによって、 <code>map</code> が呼び出された配列がまばらである場合、結果の配列もまばらとなり、要素を空欄のままにします。</p>
<h2 id="Polyfill" name="Polyfill">ポリフィル</h2>
<p><code>map</code> は ECMA-262 標準に最近追加されたものである為、標準準拠を謳う実装中に存在しない場合があります。</p>
<p>次のコードをスクリプトの先頭に挿入すると、 <code>map</code> にネイティブで対応していない ECMA-262 実装でも <code>map</code> を使用できるようになります。このアルゴリズムは ECMA-262 第 5 版で指示されたアルゴリズムと全く同じものです。 {{jsxref("Object")}}、{{jsxref("TypeError")}}、{{jsxref("Array")}} はそれぞれオリジナルの値を持ち、またそれらの {{jsxref("Function.prototype.call")}} のオリジナルの値として評価されます。</p>
<pre class="brush: js notranslate">// 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;
};
}
</pre>
<h2 id="Examples" name="Examples">例</h2>
<h3 id="Mapping_an_array_of_numbers_to_an_array_of_square_roots" name="Mapping_an_array_of_numbers_to_an_array_of_square_roots">数値の配列を平方根の配列にマッピング</h3>
<p>次のコードは、数値からなる配列を取り、それらの数値の平方根からなる新しい配列を生成します。</p>
<pre class="brush: js notranslate">let numbers = [1, 4, 9]
let roots = numbers.map(function(num) {
return Math.sqrt(num)
})
// roots の内容は [1, 2, 3] となる
// numbers の内容は [1, 4, 9] のまま
</pre>
<h3 id="Using_map_to_reformat_objects_in_an_array" name="Using_map_to_reformat_objects_in_an_array">map を使用して配列内のオブジェクトを再フォーマット</h3>
<p>次のコードは、オブジェクトの配列を受け取り、新たにフォーマットされた新しい配列を生成しています。</p>
<pre class="brush: js notranslate">let kvArray = [{key: 1, value: 10},
{key: 2, value: 20},
{key: 3, value: 30}]
let reformattedArray = kvArray.map(obj => {
let rObj = {}
rObj[obj.key] = obj.value
return rObj
})
// フォーマットされた配列の内容は [{1: 10}, {2: 20}, {3: 30}]となる
// kvArray は
// [{key: 1, value: 10},
// {key: 2, value: 20},
// {key: 3, value: 30}]
// のまま</pre>
<h3 id="Mapping_an_array_of_numbers_using_a_function_containing_an_argument" name="Mapping_an_array_of_numbers_using_a_function_containing_an_argument">引数を含む関数を使用して数値配列をマッピングする</h3>
<p>次のコードは、1 つの引数を必要とする関数を使用するときに <code>map</code> がどのように動作するかを示しています。引数は元の配列を通した <code>map</code> ループとして、配列の各要素に自動的に割り当てられます。</p>
<pre class="brush: js notranslate">let numbers = [1, 4, 9]
let doubles = numbers.map(function(num) {
return num * 2
})
// doubles is now [2, 8, 18]
// numbers is still [1, 4, 9]
</pre>
<h3 id="Using_map_generically" name="Using_map_generically">汎用的な map の使用</h3>
<p>以下の例は、各文字を表す ASCII エンコードのバイトの配列を得るために {{jsxref("String")}} に map を使う方法を示しています。:</p>
<pre class="brush: js notranslate">let map = Array.prototype.map
let a = map.call('Hello World', function(x) {
return x.charCodeAt(0)
})
// a の内容は [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100] となる
</pre>
<h3 id="Mapping_an_array_of_numbers_using_a_function_containing_an_argument" name="Mapping_an_array_of_numbers_using_a_function_containing_an_argument">汎用的な map の使用: querySelectorAll</h3>
<p>この例では、<code>querySelectorAll</code> によって収集されたオブジェクトのコレクションを反復処理する方法を示します。これは <code>querySelectorAll</code> が <code>NodeList</code> (オブジェクトの集合) を返すためです。</p>
<p>この場合、画面に選択されているすべての <code>option</code> の値を返します。</p>
<pre class="brush: js notranslate">let elems = document.querySelectorAll('select option:checked')
let values = Array.prototype.map.call(elems, function(obj) {
return obj.value
})
</pre>
<p>もっと簡単な方法は {{jsxref("Array.from()")}} メソッドを使用することです。</p>
<h3 id="Tricky_use_case" name="Tricky_use_case">トリッキーな使用例</h3>
<p>(<a href="http://www.wirfs-brock.com/allen/posts/166">このブログの記事に創発されました</a>)</p>
<p>コールバック関数は第一引数 (変換するべき要素) だけを意識して指定するケースがほとんどだと思います。しかし一般的に第一引数しか使わないような関数でも、実は追加のオプション引数を受け取っている場合があります。これは混乱につながる可能性があります。</p>
<p>まずこの例をご覧ください。</p>
<pre class="brush: js notranslate">["1", "2", "3"].map(parseInt)</pre>
<p>返値は <code>[1, 2, 3]</code> となりそうですが、実際には <code>[1, NaN, NaN]</code> となります。</p>
<p>{{jsxref("parseInt")}} は大抵一つの引数のみで使われますが、実際には二つの引数を取っています。一つ目は数値文字列、二つ目は基数です。 <code>Array.prototype.map</code> はコールバックに次の 3 つの引数を与えています。</p>
<ul>
<li>その要素</li>
<li>その添字</li>
<li>その配列</li>
</ul>
<p>{{jsxref("parseInt")}} は三つ目の引数を無視しますが、二つ目の引数は無視<em>しません</em>。これは混乱を起こす可能性があるソースです。</p>
<p>繰り返し手順の正確な例は以下の通りです。</p>
<pre class="brush: js notranslate">// parseInt(string, radix) -> map(parseInt(value, index))
/* first iteration (index is 0): */ parseInt("1", 0) // 1
/* second iteration (index is 1): */ parseInt("2", 1) // NaN
/* third iteration (index is 2): */ parseInt("3", 2) // NaN
</pre>
<p>解決策を考えてみましょう。</p>
<pre class="brush: js notranslate">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() とは違って、 Number() は float または (解決した) 指数表現を返します。
['1.1', '2.2e2', '3e300'].map(Number) // [1.1, 220, 3e+300]
// 比較のために、上記の配列に parseInt() を用いると次のようになります。
['1.1', '2.2e2', '3e300'].map( str => parseInt(str) ) // [1, 2, 3]
</pre>
<p>{{jsxref("parseInt")}} を引数として呼び出された map メソッドの代替出力の 1 つは、次のように実行されます。</p>
<pre class="brush: js notranslate">let xs = ['10', '10', '10']
xs = xs.map(parseInt)
console.log(xs)
// 実際の結果 10,NaN,2 は上記の説明からすると意外なものかもしれません。</pre>
<h3 id="undefined_を持つマップされた配列">undefined を持つマップされた配列</h3>
<p>{{jsxref("undefined")}} または nothing を返すと、以下のものを返します。</p>
<pre class="brush: js notranslate">let numbers = [1, 2, 3, 4]
let filteredNumbers = numbers.map(function(num, index) {
if (index < 3) {
return num
}
})
// index は 0 から始まるので、 filterNumbers は 1,2,3 および undefined になります。
// filteredNumbers は [1, 2, undefined, undefined]
// numbers は [1, 2, 3, 4] のまま
</pre>
<h2 id="Specifications" name="Specifications">仕様書</h2>
<table class="standard-table">
<thead>
<tr>
<th scope="col">仕様書</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{SpecName('ESDraft', '#sec-array.prototype.map', 'Array.prototype.map')}}</td>
</tr>
</tbody>
</table>
<h2 id="Browser_compatibility" name="Browser_compatibility">ブラウザーの互換性</h2>
<div>
<p>{{Compat("javascript.builtins.Array.map")}}</p>
</div>
<h2 id="See_also" name="See_also">関連情報</h2>
<ul>
<li>{{jsxref("Array.prototype.forEach()")}}</li>
<li>{{jsxref("Map")}} object</li>
<li>{{jsxref("Array.from()")}}</li>
</ul>
|