<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/xml.xsl" type="text/xsl"?><feed xmlns="http://www.w3.org/2005/Atom">
  <title>nulog, NULL::something : out of the headphone &gt; 2005 &gt; December &gt; 02 &gt; ECMAScript での var</title>
  <link href="http://lowreal.net/logs/2005/12/02/3"/>
  <icon>http://lowreal.net/img/banner.png</icon>
  <link rel="self" type="application/atom+xml" href="http://lowreal.net/logs/2005/12/02/3.atom"/>
  <link rel="alternate" type="application/xhtml+xml" href="http://lowreal.net/logs/2005/12/02/3.xhtml"/>
  <updated>2005-12-02T17:42:06+09:00</updated>
  <author>
    <name>cho45(砂糖)</name>
  </author>
  <id>http://lowreal.net/2005/12/02/3</id>
  <entry>
    <title>ECMAScript での var</title>
    <link rel="alternate" type="text/html" href="http://lowreal.net/logs/2005/12/02/3.html"/>
    <link rel="alternate" type="application/xml+xhtml" href="http://lowreal.net/logs/2005/12/02/3.xhtml"/>
    <updated>2005-12-02T17:42:06+09:00</updated>
    <published>2005-12-02T17:42:06+09:00</published>
    <id>http://lowreal.net/2005/12/02/3</id>
    <category term="javascript"/>
    <category term="script"/>
    <category term="prog"/>
    <content type="xhtml" xml:base="http://lowreal.net/">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>前に書いた気がするけど、ECMAScript の <code>var</code> は Io の setSlot に似ている。</p>
        <p><code class="ECMAScript">var foo;</code> と書くと、既存のスコープの変数オブジェクトのプロパティに <var>foo</var> が作られる。そして <code class="ECMAScript">foo = "1";</code> を書くと、スコープチェインの最初に、作られた foo プロパティを発見するため、そこに代入される。</p>
        <p>一方 <code class="ECMAScript">foo = "1";</code> を <code>var</code> 無しにいきなり書いた場合、スコープチェインの末 Global オブジェクトにいきつき Global オブジェクトのプロパティに新たに<em>勝手に</em><code>foo</code> が作られて代入される。</p>
        <pre class="ECMAScript">// 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; //=&gt; "bar"
    baz.f //=&gt; undefined
    f; //=&gt; "!!!"
}

foobar();
foo; //=&gt; "foo" 最初にグローバルで代入したまま
bar; //=&gt; "bzbz" 書き換えられている
baz; //=&gt; "baz" グローバルで一切でてきていないのに存在する</pre>
        <p>Io の場合 <code>=</code> (updateSlot) はスコープチェインに Identifier を発見できない場合例外が発生する。現在の変数オブジェクトのスロットに突っ込むときは <code>:=</code> (setSlot) を使用する。Io は明確な決まりがあるんだけど、ECMAScript は曖昧。気が付くと Global オブジェクトにプロパティがだらだらできたりする。</p>
        <p>微妙にわかりにくいのは、Global Code においての Variable Object が Global で、変数に <code>this.foo</code> というようにアクセスできるのに対し、Function Code の Variable Object には一切触れないこと</p>
        <p>ときどき関数中で <code class="ECMAScript">var a = b = c = 0;</code> って書いているのを見かけるけど、この場合の <var>b</var>, <var>c</var> は Global オブジェクトのプロパティ (または途中であるならその変数オブジェクトのプロパティ) になる。<code class="ECMAScript">var a, b, c; a = b = c = 0;</code> とか書くのが正解。</p>
        <p>Prototype Chain もそうだけど、「見えないオブジェクト」がいくつかあってなかなか怖い。</p>
      </div>
    </content>
  </entry>
</feed>
