with ステートメント

 with ステートメントは、. (ドット) 演算子における左側 (オブジェクト) を省略した場合に参照するオブジェクトを指定するものです。

 構文は以下の通りです。

with(expression)
    ステートメントまたはブロック


 「ステートメントまたはブロック」内で、左側が省略された . (ドット)演算子が使用された場合、その . (ドット)演算子が参照するオブジェクトは、with ステートメントの expression で指定したオブジェクトになります。


例:
    with(obj) .member = 1; // obj.member = 1; と同じ

    with(obj)
    {
        .member1 = 1; // obj.member1 に 1 を代入
        .member2 = 2; // obj.member2 に 2 を代入
        .member3++; // obj.member3 をインクリメント
        .method(); // obj.method を呼び出す
    }


 このステートメントは特に、オブジェクトに大量のプロパティを設定したり、連続してメソッドを呼ぶ際に、タイピングを減らすことができます。

 たとえば


    var object = new Foo();
    object.setPos(0, 0);
    object.setSize(100, 100);
    object.name = "名前無し";
    object.color = 0xffffffff;


 のようなスクリプトを以下のように書くことができます。


    var object = new Foo();
    with(object)
    {
        .setPos(0, 0);
        .setSize(100, 100);
        .name = "名前無し";
        .color = 0xffffffff;
    }


with ステートメントとオブジェクト

 with ステートメントで指定した expression は、with が実行される最初に1回だけ評価され、あとはそれを参照するだけになります。

 たとえば、


this.dic = %[];
with(this.dic)
{
    .member = 1; // this.dic.member に 1 を代入
    this.dic = 0; // dic に何か別の物を代入
    .member = 2; // this.dic.member に 2 を代入
}


 と書いても、2回目の .member への代入は成功するでしょう。with が実行される最初の状態で this.dic が評価され、あとはその評価された結果を用いているからです。毎回 this.dic を評価する訳ではありません。

 評価は最初の1回だけのため、何回もオブジェクトを参照するような用途では、オブジェクトを参照するためのコードが毎回生成されるようなことがなくなり、高速になる場合があります。

 上記の例は以下と等価のコードが生成されると考えることが出来ます。


this.dic = %[];
{
    var 無名の特別なローカル変数 = this.dic;
    無名の特別なローカル変数.member = 1;
    this.dic = 0;
    無名の特別なローカル変数.member = 2;
}


 with ステートメントでは、左側が省略された . (ドット) 演算子でしかアクセスできない、無名の特別なローカル変数に expression の評価の結果が代入され、以降、左側が省略された . (ドット) 演算子では、その「無名の特別なローカル変数」が参照されるようになります。
 expression を評価した結果が保持されるスコープも、上記の「無名の特別なローカル変数」のローカル変数スコープと同じとみなすことができます ( with ステートメントが影響を与える範囲もその通りとなります )。

with ステートメント外での . 演算子

 with ステートメント外で . (ドット) 演算子の左側が省略された場合、グローバルオブジェクトを参照することになります。
 たとえば、with ステートメント外で

.foo = 1;

 と記述すると

global.foo = 1;

 と同じ意味になります。