« 吉里吉里Java/KAG3 のメモリ消費量 | メイン | Android のメニュー »

2012年04月26日

吉里吉里 その他の開発日誌:: 気になる挙動を調べてみた

    

tjs2では特定条件で判定からはずしたブロックのdeleteが実行されるらしい? ここに記述されている内容が気になったので調べてみた。
以下スクリプトと問題点を転記。

function test()
{
 var lay = new Layer(kag, kag.fore.base);
 var result;
 if (false)
 {
  dm("run");
  result = delete lay;
 }
 dm("■result:"+result);
 dm("■lay:"+lay);
}

dm("■lay:"+lay); で、lay がないと言われて例外発生。

function test()
{
 var lay = new Layer(kag, kag.fore.base);
 if (false)
 {
  var lay;
  delete lay;
 }
 dm("■lay:"+lay);
}

このように記述すると問題なく動作する。

function test()
{
 if(false)
  var p = 0;
 dm(p);
}

dm(p); での p の値が不定。

3個目の変数アクセスの方は比較的簡単。
中かっこのない if 文はスコープをネストしないので、var で変数宣言したら上位のスコープと思えるスコープに変数が作られる。
で、dm でアクセスした時、変数はあるが初期化されていないので、未初期化変数へのアクセスとなり、値は不定。

1個目の挙動は少しやっかい。
バイトコードを出してみると、delete は通らないし、デバッガで追ってみても通らない ( そもそも delete のコードは出力されない ) 。
例外が発生するのは、dm("■lay:"+lay); で lay へのアクセスが、proxy(this or global) のメンバ lay へアクセスしようとしてメンバが見付からないところ。
なぜここでローカル変数へのアクセスではなく、メンバアクセスになっているか。
ローカル変数に対する delete がどのようになっているかを調べると、処理はコンパイル時に行われていた。
ローカル変数に対する delete のバイトコードを作るところで、ローカル変数の lay が削除されてしまうので、dm("■lay:"+lay); ではローカル変数の lay は消えているため、メンバアクセスになっている。
そして、これはコンパイル時に行われるため、if 文は関係なく、単純に前にあるか後ろにあるかによって変数があったり、なくなったりする。

2個目がなぜ通るのかと言うと、上述の処理を見ればわかる。
if 文のスコープ内にある lay 変数は削除されるが、それより外のスコープの lay は削除されず、ローカル変数へのアクセスとして解釈されて、期待通りの動作をするはず。
これは実際に処理を追ってないのである程度推測。


動作はいいとして、ローカル変数への delete はこのような仕様であると認識して使わないと意図しない記述をしてしまいそう。
と言うか、ローカル変数を delete すること自体が問題の種か。
まあ、ローカル変数を delete しようとした事はないが。
中かっこのない if 文の方は、そんなことしないから気にする必要ないと思うけど。



投稿者 Takenori : 2012年04月26日 22:57




comments powered by Disqus
Total : Today : Yesterday : なかのひと