--- title: 配列内包表記 slug: Web/JavaScript/Reference/Operators/Array_comprehensions tags: - JavaScript - Non-standard - Operator - Reference translation_of: Archive/Web/JavaScript/Array_comprehensions ---
array comprehension 構文は、既存のものに基づいている新しい配列をすばやく組み立てることができるJavaScriptの式でした。しかし、これは標準仕様や Firefox の実装から削除されました。使用しないでください!
[for (x of iterable) x] [for (x of iterable) if (condition) x] [for (x of iterable) for (y of iterable) x + y]
配列の内包表記内で、下記の二種類のコンポーネントが許されています。:
for-of イテレーションは常に最初のコンポーネントです。複数のfor-of イテレーションは、ステートメントが許可されている場合。
配列内包は以前、ECMAScript 2016 で標準化を提案されていました。これは別のものに基づいて新たな配列を構成するための手っ取り早い方法を提供します。配列内包は一般に、{{jsxref("Array.prototype.map", "map()")}} および {{jsxref("Array.prototype.filter", "filter()")}} を呼び出す代わりとして、あるいはそれら 2 つを結合する手段として用いることができます。
次の配列内包は数値の配列を取り込んで、その各数値を 2 倍した値による新しい配列を作成します。
var numbers = [1, 2, 3, 4]; var doubled = [for (i of numbers) i * 2]; console.log(doubled); // logs 2,4,6,8
これは以下の {{jsxref("Array.prototype.map", "map()")}} による操作と同等です:
var doubled = numbers.map(i => i * 2);
配列内包は、特定の式にマッチするアイテムの選択に用いることもできます。以下は、偶数だけを選択する内包です:
var numbers = [1, 2, 3, 21, 22, 30]; var evens = [for (i of numbers) if (i % 2 === 0) i]; console.log(evens); // logs 2,22,30
同じ目的で {{jsxref("Array.prototype.filter", "filter()")}} を用いることができます:
var evens = numbers.filter(i => i % 2 === 0);
{{jsxref("Array.prototype.map", "map()")}} および {{jsxref("Array.prototype.filter", "filter()")}} 方式の操作を、ひとつの配列内包に統合することができます。以下は偶数だけをフィルタリングして、それらを 2 倍した値を含む配列を作成します:
var numbers = [1, 2, 3, 21, 22, 30]; var doubledEvens = [for (i of numbers) if (i % 2 === 0) i * 2]; console.log(doubledEvens); // logs 4,44,60
配列内包の角括弧は、スコープ目的の暗黙的なブロックをもたらします。新しい変数 (上記の例における i ) は、{{jsxref("Statements/let","let")}} を用いて宣言されたかのように扱われます。つまり、それらの変数は配列内包の外部で使用できません。
配列内包の入力自体は、配列である必要はありません。イテレータおよびジェネレータ も使用できます。
文字列を入力とすることもできます。(配列状のオブジェクトにおいて) 前出の filter や map の動作を実現するには以下のようにします:
var str = 'abcdef'; var consonantsOnlyStr = [for (c of str) if (!(/[aeiouAEIOU]/).test(c)) c].join(''); // 'bcdf' var interpolatedZeros = [for (c of str) c + '0' ].join(''); // 'a0b0c0d0e0f0'
繰り返しになりますが入力データの形式は維持されませんので、文字列へ戻すために {{jsxref("Array.prototype.join", "join()")}} を使用しなければなりません。
[for (i of [ 1, 2, 3 ]) i*i ]; // [ 1, 4, 9 ] var abc = [ "A", "B", "C" ]; [for (letters of abc) letters.toLowerCase()]; // [ "a", "b", "c" ]
var years = [ 1954, 1974, 1990, 2006, 2010, 2014 ]; [for (year of years) if (year > 2000) year]; // [ 2006, 2010, 2014 ] [for (year of years) if (year > 2000) if(year < 2010) year]; // [ 2006], the same as below: [for (year of years) if (year > 2000 && year < 2010) year]; // [ 2006]
map
とfilter
を比較する配列の内包表記配列の内包表記構文を理解する簡単な方法は、Array {{jsxref("Array.map", "map")}}や{{jsxref("Array.filter", "filter")}}メソッドと比較することです。:
var numbers = [ 1, 2, 3 ]; numbers.map(function (i) { return i * i }); numbers.map(i => i*i); [for (i of numbers) i*i ]; // all are [ 1, 4, 9 ] numbers.filter(function (i) { return i < 3 }); numbers.filter(i => i < 3); [for (i of numbers) if (i < 3) i]; // all are [ 1, 2 ]
二つの配列で動作させるために二つのfor-ofイテレーションを使用する:
var numbers = [ 1, 2, 3 ]; var letters = [ "a", "b", "c" ]; var cross = [for (i of numbers) for (j of letters) i+j]; // [ "1a", "1b", "1c", "2a", "2b", "2c", "3a", "3b", "3c" ] var grid = [for (i of numbers) [for (j of letters) i+j]]; // [ // ["1a", "1b", "1c"], // ["2a", "2b", "2c"], // ["3a", "3b", "3c"] // ] [for (i of numbers) if (i > 1) for (j of letters) if(j > "a") i+j] // ["2b", "2c", "3b", "3c"], the same as below: [for (i of numbers) for (j of letters) if (i > 1) if(j > "a") i+j] // ["2b", "2c", "3b", "3c"] [for (i of numbers) if (i > 1) [for (j of letters) if(j > "a") i+j]] // [["2b", "2c"], ["3b", "3c"]], not the same as below: [for (i of numbers) [for (j of letters) if (i > 1) if(j > "a") i+j]] // [[], ["2b", "2c"], ["3b", "3c"]]
最初は ECMAScript 2015 のドラフトでしたが、リビジョン 27 (2014 年 8 月) で取り除かれました。仕様セマンティクスのために ES2015 の古いリビジョンを参照してください。
{{Compat("javascript.operators.array_comprehensions")}}
古い内包表記の構文 (使用しないでください!):
[X for (Y in Z)] [X for each (Y in Z)] [X for (Y of Z)]
違い:
[()=>x for (x of [0, 1, 2])][1]() // 2
[for (x of [0, 1, 2]) ()=>x][1]() // 1, each iteration creates a fresh binding for x.
[i * 2 for (i of numbers)]
[for (i of numbers) i * 2
]
if
とfor
コンポーネントを持ち得ます。{{jsxref("Statements/for...of", "for...of")}}
でのみ動作し、{{jsxref("Statements/for...in", "for...in")}}
イテレーションで 動作しません。コード更新の提案について、Bug 1220564 のコメント 42 をご覧ください。