Arrayの初期化子の末尾のカンマ

要旨

Arrayの初期化の動作がIEFirefoxで違う。
ECMAの仕様通りなのはIE(JScript)、
っぽい。

経緯

自動巡回のスクリプトWSH/JScriptで組んでいたが、
Windowsを98からMEに変えたとき、
ときどき動作がおかしいことがあった。
しかし、致命的ではないのでそのままほっておいてあった。
2年ほど経って、なぜおかしいのか分かった。


例えば、ニュースサイトを巡回に行くとき、


var a = [
"http://www.asahi.com/",
"http://www.itmedia.co.jp/news/",
"http://www.nikkeibp.co.jp/",
];

などと、URLをArrayに入れる。
このとき、


a.length; // 4

となっていた。
すなわち、赤字の末尾のカンマをつけると
意図どおりの動作にならないかもしれない、
ということだ。


先日、


Array#lengthの動作
http://d.hatena.ne.jp/kazuokohchi/20061106


を拝見して、ちょっと調べてみようと思っていた。
しばらくほっておいたが、
昨日、ふと思い立って、ECMA-262の仕様を読んでみた。


http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf#page=52

簡単な歴史

JavaScriptで末尾にカンマをつけてもつけなくても変わらないのは、
Cで、


int a[] = { 1, 2, 3, };

と書けるところからの連想だろう。
上のように書くときはあまりメリットがないが、


int a[] = {
1,
2,
3,
};
と書くと、保守性が向上する。
昔はこうは書けなかったはずだが、この辺は記憶違いかもしれない。
Perlでも、


my @a = ( 1, 2, 3, );

と書けるし、C系列の言語はだいたいこう書けるのではないだろうか。
(本当はよく知らない)


ところが、JScriptは、おそらくバージョン5.5で動作が変わった。


var a = [ 1, 2, 3, ];

とすると、


a.length; // 4

で、a[3]は未定義となる。
(正確にはなんだろう)

ECMAScript 3rd Edition

今のJavaScriptはたいていこれに準拠しているらしい。


http://ja.wikipedia.org/wiki/ECMAScript


この仕様書は、


http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf


これを読んでみよう(英語だが)。
問題の部分は、P.52、
11.1.4 Array Initialiser


少し引用しよう。

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.

英語苦手なのでアレなんだが、
最初あるいは最後にカンマをつけるとその分Arrayが大きくなる、
と書いてあるように読める。


なんだ、IE(JScript)が正しくなっただけか。
要するに単なる勘違いだったわけだ。