ちょっと前の記事 (AS3 で動的言語のススメ) に書いたように strict オプションを指定しないことで AS3 の記述の自由度は格段に上がります。とはいえ、"With great power comes great responsibility" の言葉どおり、選択肢が増えた分だけ、コードを記述する側の責任が大きくなることは意識しておく必要があります。
手抜きの書き方を勧めたことに少し責任を感じて、今回は var による変数宣言の有無による変数の振舞いの違いに少し触れてみたいと思います。
var 無し変数の初期化
Flash CS3 でも Flex でも AS3 コンパイラの厳密な型チェックのオプションをオフにすれば var 宣言無しで変数が使用できるようになります。例えば下のコードは問題なくコンパイルできます。
public class Foo { public function setMyGlobal(val:int):void { i = val; } public function printMyGlobal():void { trace(i); } }
以下のコードを試してみると 10 が出力されます。ちゃんと動作していることが確認できます。
var foo:Foo = new Foo(); foo.setMyGlobal(10); foo.printMyGlobal(); // 10 が出力される
ところが、setMyGlobal() を呼び出さずに printMyGlobal() を呼び出すと、実行時に i が定義されていないというエラーメッセージが出力されます。
var foo:Foo = new Foo(); foo.printMyGlobal(); // ランタイムエラー発生
このことから setMyGlobal() 内で i の初期化が行われていたことが分かります。
public function setMyGlobal(val:int):void { i = val; // この行が最初に実行された時点で i が初期化される }
値を代入するコードの実行が、最初の回に限り変数の初期化も兼ねています。つまり、コードの実行される順番に結果が依存するわけです。
var を使った宣言を行わない場合は初期化のタイミングに注意するようにしましょう。明示的に var を使って宣言した変数であればインスタンス生成時に変数の初期化が行われます。
var 無し変数のスコープ
さて、再び最初に定義したクラス Foo を使って次のコードを実行してみましょう。
var foo1:Foo = new Foo(); var foo2:Foo = new Foo(); foo1.setMyGlobal(10); foo2.printMyGlobal(); // 10 が出力される
そうすると 10 が出力されると思います。foo1 で設定した値が foo2 から参照できていることになります。つまり var を使わずに使用された変数 i はクラスのインスタンス間で共有されているわけです。
var を使わないで変数を初期化するコードを記述するのは、スタティックイニシャライザを記述するようなものだと考えてもよいでしょう。もし、Foo クラスの定義が i をインスタンス変数として定義し忘れたものだったとしたら、ずいぶんと異なる振舞いを記述していることになります。
Flash CS3 の場合なら、ムービークリップのタイムラインに var を付けずに使用している変数があれば、その値は全てのインスタンスで共有されることになるわけです。
コンパイラで厳密な型チェックを行うように指定すれば var 宣言されていない変数はコンパイル時に発見して通知してくれます。AS3 コンパイラの設定がデフォルトで strict モードになっているのはなるほどというところでしょうか。Flash 8 以前の fla を AS3 に設定しなおした場合は strict オプションは選択されていませんのでご注意を。
strictモード大変便利ですね。
今日、ちょっと不思議な現象を発見したのでPostします。
以下のサンプルをstrictモードでコンパイルすると、pwが宣言されていないのでエラーになるのはわかりますが、
f();
function f() {
pw = 20;
trace(pw);
}
以下のようなコードにするとエラーは出ませんでした。strictモードのチェックも完璧ではないのでしょうか。
f();
function f() {
pw = 20;
trace(pw);
var pw:Number = 10;
trace(pw);
}
はまださん、こんにちは。
var pw:Number = 10;
は、以下の2行をまとめて書いたものとみなすことができます。
var pw:Number;
pw = 10;
そのため、下のほうのサンプルでは pw が var 宣言されているものとして扱われます。