NULL::something

Login via flickr, はてな, TypeKey.

2005-12-02

ECMAScript での var

前に書いた気がするけど、ECMAScript の var は Io の setSlot に似ている。

var foo; と書くと、既存のスコープの変数オブジェクトのプロパティに foo が作られる。そして foo = "1"; を書くと、スコープチェインの最初に、作られた foo プロパティを発見するため、そこに代入される。

一方 foo = "1";var 無しにいきなり書いた場合、スコープチェインの末 Global オブジェクトにいきつき Global オブジェクトのプロパティに新たに勝手にfoo が作られて代入される。

// Global Code の開始
// Scope Chain: [Global]
// Variable Object: Global

//----

// Variable Object (Global)
// のプロパティ foo に "foo" が代入される。
var foo = "foo";
// 上に同じ
var bar = "bar";

function foobar() {
    // Function Code の開始
    // 新たに Activation Object (=このコンテキストでのVariable Object) が作られる。
    //   (このとき arguments プロパティが自動的にセットされる。)
    // Scope Chain: [foobarActivationObj, Global]
    //     foobarActivationObj は仮の名前で実際にはアクセスできない。
    // Variable Object: foobarActivationObj

    // Variable Object (foobarActivationObj)
    // のプロパティ foo に "fbfb" が代入される。
    var foo = "fbfb";

    // Identifier があると Scope Chain を辿る。
    // この場合最初の foobarActivationObj に foo を発見できる。
    foo = "bfbf";

    // この場合最初の foobarActivationObj に bar を発見できないため
    // Scope Chain を辿り、Global で bar を発見する。
    bar = "bzbz";

    // この場合 Scope Chain をたどって、Global に行き着いても発見できないため
    // 勝手に Global に baz プロパティを作る。
    baz = "baz";
    baz.foo = "foo";

    with (baz) {
        // with は Scope Chain の先頭に
        // 指定オブジェクトを突っ込む
        // Scope Chain : [baz, foobarActivationObj, Global]
        foo = "bar";

        // Variable Object は変わらない
        var f = "!!!";
    }
    baz.foo; //=> "bar"
    baz.f //=> undefined
    f; //=> "!!!"
}

foobar();
foo; //=> "foo" 最初にグローバルで代入したまま
bar; //=> "bzbz" 書き換えられている
baz; //=> "baz" グローバルで一切でてきていないのに存在する

Io の場合 = (updateSlot) はスコープチェインに Identifier を発見できない場合例外が発生する。現在の変数オブジェクトのスロットに突っ込むときは := (setSlot) を使用する。Io は明確な決まりがあるんだけど、ECMAScript は曖昧。気が付くと Global オブジェクトにプロパティがだらだらできたりする。

微妙にわかりにくいのは、Global Code においての Variable Object が Global で、変数に this.foo というようにアクセスできるのに対し、Function Code の Variable Object には一切触れないこと

ときどき関数中で var a = b = c = 0; って書いているのを見かけるけど、この場合の b, c は Global オブジェクトのプロパティ (または途中であるならその変数オブジェクトのプロパティ) になる。var a, b, c; a = b = c = 0; とか書くのが正解。

Prototype Chain もそうだけど、「見えないオブジェクト」がいくつかあってなかなか怖い。

Comments (0)

Trackback URI: http://lowreal.net/logs/2005/12/02/3.trackback

NULL

RSS feed meter for http://lowreal.net/logs/latest

Alternates

  1. RSS 1.0
  2. Atom 1.0

Generated with Taglibro

この日記は Taglibro と呼ばれる XML ベースの XSLT をテンプレートとして使ったシステムを使っています。現在の Taglibro は Ruby, ruby-xslt, libxml-ruby による実装です。ソースコードはとりあえず公開していません。