diff options
Diffstat (limited to 'files/ja/web/javascript/reference/global_objects/array/map/index.html')
-rw-r--r-- | files/ja/web/javascript/reference/global_objects/array/map/index.html | 366 |
1 files changed, 366 insertions, 0 deletions
diff --git a/files/ja/web/javascript/reference/global_objects/array/map/index.html b/files/ja/web/javascript/reference/global_objects/array/map/index.html new file mode 100644 index 0000000000..8d82a82e72 --- /dev/null +++ b/files/ja/web/javascript/reference/global_objects/array/map/index.html @@ -0,0 +1,366 @@ +--- +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> +<div class="hidden">このページの互換性一覧表は構造化データから生成されています。データに協力していただけるのであれば、 <a class="external" href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> をチェックアウトしてプルリクエストを送信してください。</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> |