トップ «前の日記(2011-09-15) 最新 次の日記(2011-09-18)» 編集

日々の破片

著作一覧

2011-09-16

_ JavaScriptが難しいのではなくIEが難しくしてくれている

IE9で開発していて、次のように書いた。

var keywords = ['ab', 'cd', 'ef', ];
for (var i = 0; i < keywords.length; i++) {
  obj[keywords[i]] = getValue(keywords[i]);
}

で、動いたもので実環境へ持っていく。そこではIE8が動いていた。

ら、死ぬ。

不思議に思っていろいろ動かしてみたら、IE8では、[1,2,3,]は4要素(length == 4)、IE9では3要素(length == 3)ちなみにChromeも3要素ということがわかった。

はて、どちらが正しいのか。順当にはバージョンが新しいIE9が正しそうだ。かつ、そちらのほうが直観に近い。直観というよりも、JavaやCの印象からだけど。

int[] array = {
  1,
  2,   // 後で末尾に要素を追加したときに楽ちん
};

そこで、ECMAの仕様を読むと、難しい。

the missing array element contributes to the length of the Array and increases the index of subsequent elements.

IE8が正しい?

If an element is elided at the end of an array, that element does not contribute to the length of the Array.

いや、IE8がバグだ。

追記:@matarilloさんがツッコミを入れているけど、古い仕様書探すのってめんどうだからいやなんだけどな。Arrayなんて基本的なオブジェクトの仕様が変わるってことも考えられないし。

が、しょうがないので、第3版を見てみる。

, the missing array element contributes to the length of the Array and increases the index of subsequent elements. Elided array elements are not defined.

OK。わかったよ。最後の要素については何も書いてない。であれば、省略した要素は要素数に数えられるわけだからIE8が正しい。

試しにVirtual PCに確保しているXPの古いマシンを動かして、javascript:alert([1,2,3,].length);をIE6のアドレスバーに入れてみる。確かに4って表示されるじゃん。そうだったのか。これは、ECMAScript5の仕様策定が難航するはずだよ。過去の互換性を切り捨てる羽目になったのが過去の互換性を保つことで成功してきた企業なんだからなぁ。

さらに追記:でも待てよ。

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.

最初からちゃんと読むと、「配列要素は要素リストの最初、中間、最後で省略できる。要素リスト内のコンマが値設定式に先行されない場合、省略された配列要素は要素数に組み込まれ、後続の要素のインデックスは増加する。省略した要素は未定義とする。」となる。

最後で省略できるとあるから、[1,]という書き方はOKだ。だが、the missing array elementの要件であるnot preceded by an AssignementExpressionを満たしていない。したがって、[1,]というのは、後半のthe missing array element contributes to the ... が有効にならない(というのはnot preceded by an AssignmentExpressionを満たしていない)ので、結果、要素数は1が正しいのではなかろうか。というか、正しいとおれには読める。第5版はわかりやすく最終カンマの解釈にぶれがないように明記したというだけだ。

[,]であれば、要素数は1。[1,]も要素数は1。[,2]は要素数は2。

というわけで、少なくともおれの読解では1999年以来、IEのJavaScript実装はバグだということになる。で、IE9でやっとインターネット標準に軌道修正したということだ。

というような面倒なことがあると、おれが持っているのはえらく古い(多分初版か2版)から、買い直しとこうかなとか思わなくもない。

JavaScript 第5版(David Flanagan)

2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|05|06|07|08|09|10|11|12|

ジェズイットを見習え