サイトトップ

Director Flash 書籍 業務内容 プロフィール

Macromedia Flash非公式テクニカルノート

withステートメントについて

ID: FN0608001 Product: Flash

Platform: All
Version: Flash MX 2004 and above

withステートメントを使うと、{}ブロック内でターゲットなしにプロパティを記述したとき、指定したオブジェクトを最初に参照して値を取出したり、設定したりすることが可能になります。ただし、注意すべき点も少なくなくありません。それらの注意点を知らずに記述したスクリプトは、意図しない動作結果をもたらすことがあります。ですから、とくに初心者に対しては、使用は控えることをお勧めします。

本稿は、withステートメントの基本的なポイントとその注意点、およびwithステートメントを使わない記述方法などをご紹介します。

1. withステートメントの記述
withステートメントは、以下のようなスタイルで記述します。

with (オブジェクト) {
   ステートメント;
}

オブジェクトには、参照すべきMovieClipインスタンスなどのオブジェクトを指定します。すると、withステートメントブロック内でターゲットパスなどの参照なしに記述されたプロパティは、指定したオブジェクトがまず参照され、そのプロパティが存在すれば値の取得や設定が行われます。

なお、ここで「プロパティ」というのは、インスタンスのプロパティだけでなく、メソッドや、インスタンスに設定された変数なども含まれます。

withステートメントは、とくにターゲットパスが長い場合に利用すると、そのインスタンスに対する処理をすっきりと記述することができます。たとえば、つぎのサンプル(スクリプト001)は、空のMovieClipインスタンス_root.parent_mc.child_mcに100ピクセル四方の正方形を描き、その左上隅を座標(10, 10)に配置します(図001)。

スクリプト001■_root.parent_mc.child_mcに青い矩形を描く

// フレームアクション
_root.parent_mc.child_mc.beginFill(0x0000FF);
_root.parent_mc.child_mc.lineStyle(2, 0);
_root.parent_mc.child_mc.moveTo(0, 0);
_root.parent_mc.child_mc.lineTo(100, 0);
_root.parent_mc.child_mc.lineTo(100, 100);
_root.parent_mc.child_mc.lineTo(0, 100);
_root.parent_mc.child_mc.endFill();
_root.parent_mc.child_mc._x = 10;
_root.parent_mc.child_mc._y = 10;

図001■MovieClipインスタンスにスクリプト(描画API)で描かれた正方形
図001
100ピクセル四方の正方形が左上隅座標(10, 10)に表示

このスクリプト001に対し、withステートメントを使ってMovieClipインスタンスのターゲットパスを指定すると、つぎのようにすっきりと記述することができます(スクリプト002)。

スクリプト002■withステートメントでMovieClipのパスを指定

// フレームアクション
// withステートメントでMovieClipのパスを指定
with (_root.parent_mc.child_mc) {
  beginFill(0x0000FF);
  lineStyle(2, 0);
  moveTo(0, 0);
  lineTo(100, 0);
  lineTo(100, 100);
  lineTo(0, 100);
  endFill();
  _x = 10;
  _y = 10;
}

2. withステートメントの注意点
withステートメントを使った場合の第1の難点は、シンタックスカラーが適用されず、コードヒントも表示されないことです(図002)。参照を指定しなければ、メソッドに識別子のシンタックスカラー(デフォルトでは青)が適用されません。また、ドット(.)も打たないのでコードヒントが表示されず、ポップアップメニューのリストからメソッドを選択することもできません。

そして、MovieClipに対して存在しないメソッド(関数)を呼出しても、ActionScriptは何もエラーを返しません。したがって、実行してみるまで、メソッド名の記述が正しいかどうか確認する手段はないことになります。

図002■シンタックスカラーが適用されず黒で表示されたメソッド
図002
コードヒントも表示されない

注意すべき点の第2として、withステートメントは、指定したオブジェクトに新たなプロパティが設定できないということです。つまり、オブジェクトには、値を設定しようとするプロパティが、予め備わっていなければなりません。参照するオブジェクトにプロパティが存在しない場合には、withステートメントがないときと同じように処理され、プロパティの設定が行われてしまいます。

たとえば、つぎのサンプル(スクリプト003)では、withステートメントで指定するMovieClipインスタンスに、予め変数aを設定しています。しかし、変数bは設定しない(未定義の)まま、withステートメントブロック内で、aとbに値を設定しました。

スクリプト003■予め設定した変数と未定義変数にwithステートメントで値を設定

// フレームアクション
_root.parent_mc.child_mc.a = 0;   // 予め変数を設定
with (_root.parent_mc.child_mc) {
   a = 1;
   b = 2;   // 未定義変数に値を設定
}
// 確認用
trace(_root.parent_mc.child_mc.a);   // 出力: 1
trace(_root.parent_mc.child_mc.b);   // 出力: undefined   // 変数値は設定されない
trace(this.b);   // 出力: 2   // 記述したタイムラインに変数が設定

予め設定されていた変数aは、withステートメントブロック内で値を変更することができました。したがって、代入された値1が出力されています。しかし、変数bは未定義ですので、withステートメントでは設定ができません。すると、withステートメントがない場合と同じく、スクリプトの記述されたタイムラインに変数bが設定されてしまいました。

3. ActionScript定義済みプロパティやメソッドにも注意が必要
ユーザーが定義する変数でなく、ActionScriptの定義済みプロパティやメソッドでも問題がない訳ではありません。たとえば、MovieClipインスタンスに、withステートメントを用いて、イベントハンドラメソッドを設定してみましょう。

MovieClipインスタンスのターゲットパスは、これまでのサンプルと同じ_root.parent_mc.child_mcです。MovieClip.onReleaseイベントハンドラメソッドを設定しますので、MovieClipシンボル内にはヒット領域となるシェイプを描いておきます。シンタックス上は、以下のスクリプト004でよさそうに見えます。ところが、指定したMovieClipインスタンスに、イベントハンドラメソッドは設定されません。

スクリプト004■withステートメントでMovieClipにイベントハンドラメソッドを設定

// フレームアクション
// つぎのステートメントを有効にすればイベントハンドラメソッドが設定可能
// _root.parent_mc.child_mc.onRelease = undefined;   // 何でもいいので値を設定
with (_root.parent_mc.child_mc) {
  onRelease = function () {
    trace(this);   // テスト用にパスを[出力]
  };
}

MovieClipのイベントハンドラメソッドは、実際に設定されるまでは未定義(undefined)の状態になっています。そのため、内部的には未定義変数と同様に扱われるようです。

スクリプト004でwithステートメントの前の行のコメントアウトを外して有効にすると、イベントハンドラメソッドMovieClip.onReleaseに値としてundefinedが設定されます。すると、メソッドは未定義でなく、undefinedという値をもった存在として認識されるため、withステートメントブロック内でのfunction(関数)設定が正しく行われるようになります。

プロパティの例としては、MovieClip.enabledがやはりwithステートメントブロック内からいきなり値を設定することはできません[*1]

[*1] もっとも、MovieClip.enabledプロパティの初期値を調べると、undefinedでなくtrueが返されます。この結果をみると、プロパティがすでに設定されているように思えます。

しかし、実際には、enabledプロパティはコンストラクタ関数のprototypeに定義されており、インスタンスにプロパティが設定されている訳ではありません。したがって、この場合も内部的に未定義変数と同じ扱いになると考えられます。

なお、prototypeによるクラスのプロパティ定義については、「ActionScript 2.0と1.0の継承について」をご参照ください。また、MovieClip.enabledプロパティをwithステートメントブロック内で設定した場合の問題については、FLASH-japan「withの使い方」で詳しく議論されました。

4. withステートメントを使わない記述
前述2でご紹介した注意点は、とくに初心者には記述ミスを招きやすく、また意図しない結果になったときに原因が見つけにくいものとなりがちでしょう。さらに、3のActionScript定義済みのプロパティ・メソッドについては、中級者以上でも個別に調べないかぎりは、withステートメントで設定可能かどうかの判断はつかないものと思われます。

したがって、筆者としては、初心者はwithの使用は控えた方がよく、中級者以上であっても限定的に用いるべきだと考えます。そこで、withに替わる方法として、オブジェクトの参照を別の変数、とくにfunction(関数)内であればローカル変数に設定することを提案します。たとえば、スクリプト001と004を組合わせた場合、つぎのように記述します(スクリプト005)。

スクリプト005■変数にMovieClipのパスを設定

// フレームアクション
// MovieClipのパスを変数に設定
var _mc:MovieClip = _root.parent_mc.child_mc;
_mc.beginFill(0x0000FF);
_mc.lineStyle(2, 0);
_mc.moveTo(0, 0);
_mc.lineTo(100, 0);
_mc.lineTo(100, 100);
_mc.lineTo(0, 100);
_mc.endFill();
_mc._x = 10;
_mc._y = 10;
_mc.onRelease = function() {
  trace(this);
};

まず、withステートメントを使ったスクリプト002と比べて、とくに見にくいということはないでしょう。むしろ、各ステートメントごとにターゲットを明記している方が、スクリプトとしてわかりやすいと受取る人もいると思われます。

つぎに、シンタックスカラーが適用され、コードヒントも表示されますので、タイプミスを防ぎながら安心してスクリプトが記述できます(図003)。もちろん、インスタンスに未定義のプロパティも、問題なく設定することが可能です。

図003■シンタックスカラーが適用されコードヒントも表示される
図003
識別子は青く示されコードヒントからアイテムを選択できる

_____

作成者: 野中文雄
作成日: 2006年8月3日


Copyright © 2001-2006 Fumio Nonaka.  All rights reserved.