MDN wants to learn about developers like you: https://qsurvey.mozilla.com/s3/MDN-dev-survey

非標準。使用しないでください!
配列内包は非標準です。将来向きの用途には、Array.prototype.mapArray.prototype.filterアロー関数スプレッド構文 の使用を検討してください。

array comprehension構文は、既存のものに基づいている新しい配列をすばやく組み立てることができるJavaScriptの式です。内包表記は、多くのプログラミング言語に存在しています。

ECMAScript第4版の提案に基づく、SpiderMonkeyでの古い配列の内包表記構文の違いについて下記をご覧ください。

構文

[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 で標準化を提案されていました。これは別のものに基づいて新たな配列を構成するための手っ取り早い方法を提供します。配列内包は一般に、map() および 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

これは以下の 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

同じ目的で filter() を用いることができます:

var evens = numbers.filter(i => i % 2 === 0);

map() および 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 ) は、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'

繰り返しになりますが入力データの形式は維持されませんので、文字列へ戻すために 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" ]

if文で配列の内包表記

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] 

mapfilterを比較する配列の内包表記

配列の内包表記構文を理解する簡単な方法は、Array mapfilterメソッドと比較することです。:

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 の古いリビジョンを参照してください。

ブラウザ実装状況

機能 Chrome Firefox (Gecko) Internet Explorer Opera Safari
基本サポート 未サポート 30 (30) 未サポート 未サポート 未サポート
機能 Android Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
基本サポート 未サポート 未サポート 30.0 (30) 未サポート 未サポート 未サポート

SpiderMonkey固有の実装メモ

  • 識別子としてのletはサポートされていません。というのも、letは現在JSバージョン1.7とXULスクリプトタグにのみ使用できるからです。
  • 内包表記での構造化代入はまだサポートされていません(バグ 980828).

古いJS1.7/JS1.8の内包表記との違い

JS1.7/JS1.8 の内包表記は、バージョン 46 で Gecko から削除しました (バグ 1220564)。

古い内包表記の構文 (使用しないでください!):

[X for (Y in Z)]
[X for each (Y in Z)]
[X for (Y of Z)]

違い:

  • ESNext の内包表記は全体の内包表記のかわりに"for"ノードごとに1スコープを生成します。
    • 旧: [()=>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.
  • ESNext の内包表記は代入式のかわりに"for"で始まります。
    • 旧: [i * 2 for (i of numbers)]
    • 新: [for (i of numbers) i * 2]
  • ESNext の内包表記は複数のifforコンポーネントを持ち得ます。
  • ESNext の内包表記はfor...ofでのみ動作し、for...inイテレーションで 動作しません。

コード更新の提案について、Bug 1220564 のコメント 42 をご覧ください。

関連情報

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

 このページの貢献者: yyss, shide55
 最終更新者: yyss,