経緯
自動巡回のスクリプトを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が大きくなる、
と書いてあるように読める。