変数のスコープ

どこにスクリプトを書けばいい?

 スクリプトは、フレームとムービークリップとボタンに書ける。
 しかし、全体で使うための関数とかオブジェクトのクラス定義とか、どこに書けば良いのか?
 最初は、大域スクリプトのようなものがあって、そこに定義しておくのかと思っていたが、そうではないようだ。

 で、結論から行くと1フレーム目のフレームスクリプトに書くものらしい。
 1フレーム目というのは、loadイベントとか、いろいろと特殊なことが起きるし、初期設定に限り使って、そこでいろいろなアクションをするのはあまりスマートではないようだ。goto関連に、ちょっとしたバグもあるみたいだし。
 それに、オブジェクト生成前にオブジェクトにアクセスしようとしても無視されるので、確実に生成されている、次のフレームから使うようにするのが無難。
 1フレーム目では、よけいな処理はせず、2フレーム目が本当の始まりと思ってアニメーションとかはじめよう。

 しかし、HyperCardで言うところのスタックスクリプトが無いのは非常に分かりにくい。
 Flashは、いろいろと拡張を繰り返してきた跡が、あちこちにあって、いまいち言語仕様に哲学を感じないよ。Flash5でリニューアルした時に、もう少し整理されたオブジェクトの包含関係を作れたような気もするんだがねぇ。
 つーかHyperCardは参考にされなかったんだろーか?まぁ、HyperCardのオブジェクト構成が最高かと言えば、突っ込みどころも多いんだけど。

大域変数

 さて、全体で使うと言えば、大域(global)変数である。
 どーでも良いが、大域変数なんて使ってる人、ほとんど見ないな、みんなグローバル変数と呼ぶけど、鳶嶋工房は大域変数と局所(local)変数とで行く。漢字の方がイメージしやすいよ、やっぱり。
 とは言え、算譜(program)とか窓(window)とまでは書かんけど。
 さて、話がそれたが元に戻そう。
 Flashにおける大域変数である。

 従来のFlashの大域変数と言えば、実のところクラス(インスタンス)変数であって、別のオブジェクト(インスタンス)からアクセスすることは基本的にできないものだった。
 正確に言うと、インスタンスのパスを指定してやれば読めるのだが、クラス変数にアクセスすることは、オブジェクト指向的に行儀の悪いものなので、あまり勧められたものではない。
 FlashMX(6)では、_globalを利用して、真の大域変数が定義できる(いや、真かどうかは怪しいんだけど)

_global.gVar = "大域変数"

 このような、単純な大域変数は、そうそう使わない。
 というのも、がんがん大域変数を作っては、スクリプトがスパゲッティ化すること間違いなしなので、使うにしても、上品に数個程度にしたい。

_global.gFnc = function() {return "大域関数";}

 ECMAScript(JavaScript)では、関数は変数の一種として定義できる。
 このような大域関数は、大域変数よりは良いものの、あまり多用するものでもないだろう。
 じゃあ_globalは何に使うのか、と言う話になるが、これはもうオブジェクトの定義しか無いだろう。

_global.gObj = function(x,y) {
	this._x = x;
	this._y = y;
	this.dispLoc = function() {
		trace(this._x+","+this._y);
	}
}

 なんてなコンストラクタを作る。
 んで、後はインスタンスを生成して、いろいろと使えば良いわけだ。
 とは言え、オリジナルのオブジェクトを作る必要が出ることは、当分の間ないと思われるので、一応確認と言う感じで。
 次のようにして、適当なフレームなりクリップスクリプトで使える。

var theInstance = new gObj(1,2);

theInstance.dispLoc();

 _xのような、ActionScriptで定義されている属性(property)を、オリジナルのオブジェクトの属性に使っても、問題は無いようだ。
 ActionScriptの仕様にあわせて、属性は_を前につけることにする。
 このような属性(クラス変数)に外部からアクセスすることは、コレまた混乱の元なので、極力避けたいのだが、JavaScriptはクラス変数を隠ぺいできないので、チューイ。
 スコープがどんな感じなのか、ちょいと調べてみたが分からない。また、本格活用する時にでも、調べ直すことにしよう。

インスタンス変数

 ややこしいんだけど、Flashでグローバル変数と言ったら、5ではインスタンス変数(インスタンス内でなら、どこからでも使える変数)のことだったようだ。
 で、現在MXで5でのグローバル変数を何と呼んでいるかと言うと、グローバル変数らしい。…駄目じゃん。
 と言うわけで、鳶嶋工房では、一般的な呼び方が分かるまで、5でのグローバル変数をインスタンス変数と呼ぶことにする。

 で、このインスタンス変数の定義の仕方は、いたって簡単。属性(property)に近いので、とりあえず、命名法もActionScriptの属性に多い、前にアンダースコアをつけるものとしておく。

_instanceV = "初期値";

 と、代入すれば良いだけ。というか、いきなり使っても、undefaindという値が取り出せる変数として使えてしまう。
 スクリプトとしては、普通ではあるけど、ちゃんと定義させてほしい気もする。
 一応、定義するためにvarという用語が用意されているが、関数内だと局所変数となり、地の部分(関数外)で定義するとインスタンス変数になると言う、少々分かりづらい仕様。

var _instanceV = "初期値";//これはインスタンス変数
function x(){
	var localV = "初期値";//こっちは局所変数
}

 鳶嶋工房では、とりあえずFlashの常識的なコーディングパターンが分かるまで、インスタンス変数は、常にvarを使わずいきなり代入で定義することにする。コレで、一行見ただけで、局所変数の定義との区別がつく。
 アンダースコアでも区別が付くんだけどさ。

局所変数

 最後に、局所変数は、どこまで局所変数か?、と言うことを調べておこう。
 つまり、スコープが関数内なのか、ブロック内なのか、と言うことだ。

x();
function x() {
	for (var i = 0; i < 1; i++) {
		var a = "定義";
		trace("ブロック内 = " + a);
	}
	trace("ブロック外 = " + a);
}

 と、こんなスクリプトをフレームに書いて実行させてみたところ。出力は、次のような感じ。

ブロック内 = 定義
ブロック外 = 定義

 ブロック単位でなくて、関数単位での局所化と言うことですな。
 今日はここまで。


2003-07-08