2013年4月20日土曜日

`var status = ['alpha','beta','gamma'] ; typeof status`

ECMA-262処理系を実装したウェブブラウザーで次のコードを実行したとしよう。
var status = ['alpha','beta','gamma'] ; typeof status
さあ、答えは何だろうか?

ECMA-262のコードとしては初歩的でどうという事の無いものだ。変数を定義して、それからその変数の型を確認している。対話的なコンソールで実行すれば変数statusが何型なのか答えを見せてくれるだろう。Chromium-25.0.1364.160曰く、
"string"
と。

すぐに気付いた人も居るかもしれないが、参考として同様のECMA-262処理系としてのV8を搭載したnodejsで同じコードを評価するとどうなるか示す。nodejs-0.6.19曰く、
'object'
と。

そろそろ多くの方は気付いて居るだろうか。この"問題"はウェブブラウザーでしか発生しない。著者はわざわざ試して居ないがFxでもIEでも同様の結果、つまり"string"に相当する結果が得られるだろう(どうやらIEやFxでは発症せずwebkitの実装に原因がありそう; コメント参照)

この挙動は処理系のバグか?答えは勿論バグではない、仕様だ。では仕様がバギーなのか?ある意味ではそうだが、ブラウザーの仕様はバギーではない。ECMAScriptとはそういうものなのだ。


これだから動的型付けだのスクリプト言語だのというやつは嫌なのだ。特にJavaScriptというやつは言語仕様に扱いの難しい特殊な点が多いし後方互換性の維持は高速化の明らかなボトルネックの1つでもあるが、何故かWEB屋の連中は言語仕様もろくに理解していない癖にこの複雑怪奇なプログラム言語を愛して止まない。全く不可解だ。

希望: <script type="text/haskell">とか<script type="text/cpp">とか

ウェブブラウザーはスクリプトエンジンを切り離してユーザーが自由にエンジンを追加、変更、削除できる仕組みに向かって欲しいな。個人的な希望ね。LLVM.jsなんてのもあったけど、そうじゃない、そこは逆だろう?とね。

2 件のコメント:

  1. とても興味深い問題ですね。
    Windows 7 Home Premium SP1 64bit上のInternet Explorer 10.0.4、Firefox 20.0.1、Opera 12.15における開発者ツールで試してみたところ、'object'を返しました。
    そして、以下のように即時関数で変数のスコープを限定して実行すると、Chrome 26.0.1410.64、及びChromium 28.0.1483.0 (194957)における開発者ツールでも'object'を返しました。

    (function () {
    var status = ['alpha', 'beta', 'gamma'];
    return typeof status;
    }());

    しかし、以下のコードを実行すると'string'を返します。
    document.head.appendChild(document.createElement('script')).textContent = "var status = ['alpha', 'beta', 'gamma']; alert(typeof status);";

    この結果から考えると、恐らくこの問題はWebKit/Blinkの実装(グローバルコンテキスト関連?)に原因があるのかもしれませんね。

    返信削除
    返信
    1. IE、Fxでの検証情報等ありがとうございます。てっきり世のブラウザーたちはどれも似たような実装になっているのだろうと思い込んで居たので、テスト結果を教えて頂けてとても嬉しいです。

      また、コメント頂いたクロージャー内部での関数スコープに束縛して定義された変数による遮蔽とグローバルでのテスト結果は仰る通りどうもwebkit/blinkの実装、設計に原因があるのでしょうね。

      通常は敢えてstatusの様な既知のシンボルを使おうとしませんし、今時のスコープを強く意識しての設計を行うならばどうでも良い問題ではありますが、実用ではなく仕様を考えると少々気味の悪い不思議現象ですね。

      削除