LINDORのAdvent Calendar(本物)の9日目を開けたところ。
配列とかおれおれAdvent Calendar2018 – 09日目

[] のやつです。初期化子 (initializer) と呼ばれます。 「リテラル」と呼んでも差し支えない。はず。

説明

仕様書では以下のように説明されています。

12.2.5 Array Initializer

(Note: An ArrayLiteral is an expression describing the initialization of an Array object, using a list, of zero or more expressions each of which represents an array element, enclosed in square brackets. The elements need not be literals; they are evaluated each time the array initializer is evaluated.)

Array elements may be elided at the beginning, middle or end of the element list. Whenever a comma in the element list is not preceded by an AssignmentExpression (i.e., a comma at the beginning or after another comma), the missing array element contributes to the length of the Array and increases the index of subsequent elements. Elided array elements are not defined. If an element is elided at the end of an array, that element does not contribute to the length of the Array.

12.2.5 配列初期化子

(ノート:ArrayLiteral は配列オブジェクト生成を記述する式。角括弧に囲まれた、それぞれが配列要素を表す0個以上の式から成るリストを用いたもの。要素はリテラルである必要はなく、配列初期化子が評価されるたびにそれらも評価される。)

要素リストの先頭や途中、末尾の配列要素は省略してよい。 要素リスト中のカンマが AssignmentExpression に続いていない (not preceded) 場合(例:先頭や他のカンマの後ろのカンマ)、欠落した配列要素は配列の長さに影響し、続く要素のインデックスを増やす。 省略された配列要素は定義されない (not defined) 。 配列の最後の要素が省略された場合、その要素は配列の長さに影響しない。

まとめ

  • [ item1, item2, … ] という形
    • このうち item1 等が AssignmentExpression
  • 要素を省略してカンマだけ書ける(例えば [ ,,, ] も正しい)
  • 末尾の省略は無視されるので、 [ item1 , ][ item1 ] は同じ

他の配列の要素を取り込む

スプレッド構文 ... を利用して、他の配列を新しい配列の一部として利用できます。

const arr1 = [11, 22, 33];
const arr2 = [0, ...arr1, 99];
console.log(arr2); // => [ 0, 11, 22, 33, 99 ]
console.log(arr2.length); // => 5

... を付けないと、展開されないので、なんかこう、残念な結果になります。

const arr1 = [11, 22, 33];
const arr2 = [0, arr1, 99];
console.log(arr2); // => [ 0, [ 11, 22, 33 ], 99 ]
console.log(arr2.length); // => 3
console.log(arr2[1]); // => [ 11, 22, 33 ]

要素の省略

要素の記述なしにカンマ , だけ置くことで、省略 (elision) が発生します。

const arr = [11, , 22];
// --------------^
console.log(arr); // => [ 11, <1 empty item>, 22 ]
console.log(arr.length); // => 3

arr[1]undefined を返しますが、それが値として設定されているわけではありません。

empty itemsのところで説明します。

末尾カンマ

いわゆるケツカンマ。

最初にいきなりカンマ , を置くとempty slotになるけれど、末尾にカンマを置いた場合は何も起こりません。

const arr = [
  11,
  22,
  33,
];
console.log(arr); // => [ 11, 22, 33 ]

一行で書いても同じ。

const arr = [11, 22, 33, ];
console.log(arr); // => [ 11, 22, 33 ]

[] は確実に配列を生成する

配列初期化子 [] を用いた場合、内部に持っている固有オブジェクト %ArrayPrototype% をプロトタイプとしてオブジェクトが生成されます。そのため、 window.Arrayglobal.Array やらを置き換えたとしても影響はありません。

昔のJavaScriptでは置き換えると影響が出ていたんだとか。

In JavaScript 1.5 and earlier versions, it was possible to override Primitive Object’s constructor, and have this overridden version called when using bracket notations.

JavaScript 1.5以下のバージョンでは、プリミティブオブジェクトのコンストラクターをオーバーライドすることが可能でした。そして角括弧表記を使うとそのオーバーライドされたものが呼ばれててしまうのでした。

1.5は相当前だなあ。

角括弧 [ ] の名前

日本語ではつの括弧、英語ではブラケット brackets です。これ豆な。

おしまい

よく使うよね、配列リテラル。コンストラクターから作るひとはなかなかいないと思う。

気付いたんだけど、この文法は読みやすいので、仕様書を初めて読んでみる方にもおすすめです。

入れ子になって定義されている。他の章へ飛ぶ部分が比較的少ない。

関連

参考