« 最大値と最小値の間を取るとき | メイン | 既存のメソッド実行時に他の関数を同期させる »

2007年11月17日

[連載] デザイナーのためのActionScript講座 ― 第7回:続・オブジェクトと関数

しつこいようですが、もう少し関数について書いておきます。
前回オブジェクトについて書きましたが、それに関連して、もう少し関数をほじくり返してみます。

本題に入る前に、少し予備知識として話しておくことがあります。
Object には予めいくつかのプロパティやメソッドが定義されています。
これは Object に限った話ではないのですが、今はまだ Object の話しかしていないので、他の話はひとまずおいておきます。

また、ActionScript のバージョン 2 と 3 で定義されている内容は異なりますが、今は AS2 を基に話をすすめていきます。

で、Object に予め定義されているメソッドの中に toString() というものがあります。
これは Flash8 のヘルプには「指定されたオブジェクトをストリングに変換し、返します。」とあります。
つまり、この関数 toString() が定義されている Object を、人が読める形の String(文字列)に変換します。
用途は使いようによって様々ですが、今回は、主な目的のひとつである trace() 関数を使ったときに、出力する文字列を指定するために使います。
toString()の使い方は前回オブジェクトに定義した関数を使うときと同じです。
まずは以下のソースを見てください。
var obj = {};               // 変数 obj に新しく定義したオブジェクトを代入
var str = obj.toString();   // 変数 obj のtoString() 関数を呼び出して、結果を変数 str に代入
trace(str);                 // output : [object Object]
toString()の結果として"[object Object]"が出力されていることがわかります。
実際は trace() 関数を使用すると、内部でtoString()を呼び出すようになっているので わざわざ toString() を実行する必要はありません。
trace()の処理をわかりやすくすると以下のような感じです。
function trace( arg )
{
  出力( arg.toString() );
}
このtoString()を上書きして、新たに定義しなおしてみます。
var obj = {}
obj.toString = function()      // 変数 obj が持つオブジェクトのメソッド toString を上書き
{
  return "Method : toString";  // 定義内容を変更
}
trace( obj );                  // output : Method : toString
trace() の結果から toString が意図した通りに処理が書き換えられたのが分かります。

さて、前置きがかなり長くなりましたが、ここから本題です。
なるだけ分かりやすいようにHTMLの構造を真似てオブジェクトを組み立ててみます。
このオブジェクトを定義するために、折角ですから関数を用いることにします。
// ソースコード : 1
// オブジェクトを作成するための関数
function createObject( objName, objValue )
{
  var obj = { name : objName };   // name プロパティを持つオブジェクトを定義
                                  // name プロパティの値は引数 objName の値を設定する
  obj.toString = function()       // オブジェクトのtoString関数の処理を再定義
  {
    return objValue;              // 実行結果に引数 objValue の値を返すようにする
  }
  return obj;
}
続いてこの関数を用いてオブジェクトを定義します。
// ソースコード : 2
// 関数createObjectを用いてオブジェクトを定義していく
var html = createObject("html","HTML");
html.head = createObject("head","HEAD");
html.head.title = createObject("title","続・オブジェクトと関数");
html.body = createObject("body","BODY");
さて準備ができましたので、次に定義したオブジェクトが、実際どのようになっているかを探ってみましょう。
trace( html ); // output : HTML
上記のようにオブジェクト"html"を出力すると、関数createObject の引数に設定した objValue の値、つまり"HTML"が出力されました。
オブジェクト"html"のnameプロパティを参照する場合は以下のように書きます。
trace( html.name ); // output : html
お気づきかも知れませんが、このオブジェクトは階層構造になっています。
オブジェクト "head" はオブジェクト "html" のプロパティとして設定されており、さらにオブジェクト "title" はオブジェクト "head" のプロパティとして定義されています。
つまり、"html" の namehead は、同じオブジェクト "html" のプロパティであるということです。
ですので、オブジェクト "head" を参照する(この場合 trace で出力する)には
trace( html.head );
と書けばいいだけです。
それでは、オブジェクト "title" のnameプロパティを参照するにはどのように書けばよいでしょうか。
答えは次回に持ち越しますので試してみてください。

今度はソースコード:1の関数をを少し変更してみます。
// ソースコード : 1
function createObject( objName, objValue )
{
  var obj = { name : objName };
  obj.toString = function()
  {
    return objValue;
  }
  obj.outputName = function()  // 新たにメソッドを追加
  {
    trace( this.name );        // name プロパティの値を出力する
  }
  return obj;
}
新たにthisという言葉が入っています。
thisは実行しているオブジェクト自信を指すためのキーワードです。
オブジェクト"body"のメソッド"outputName()"を使うときも、プロパティと同様です。
html.body.outputName(); // output : BODY
ファイルやフォルダの関係は階層構造になっていますよね。
そのときファイルを指すURIは"/"(スラッシュ)を用いて階層構造を表しますが、それと同様です。
ただ"/"が"."になっているだけです。

以下に応用例を書いておきますので、また実際に実行してみていろいろ模索してみてください。
function node( name , child )
{
  var obj = { name:name , child:child , parent:undefined };
  child.parent = obj;
  obj.toString = function()
  {
    return this.name + "/" + this.child.toString();
  }
  return obj;
}
var source = node("1st", node("2nd", node("3rd", undefined )));
trace( source );
var anchor = source.child.child;
trace( anchor.name );
anchor.child = node( "4th", undefined );
trace( anchor.child.name );
trace( anchor.parent.name );
undefinedとは、「指定された名前は、まだ定義されていません」という意味です。
いきなり難易度を上げてしまったかもしれませんが、これが理解できれば後がかなりスムーズに理解できるようになると思いますので がんばって試行錯誤してください。

PICUP : this について

thisを用いることで参照先を明確にすることができます。
なぜ参照先を明確にしなければならないか、なのですが、その説明の前に以下のソースをコピーして実際にFlash上で実行してみてください。
// ---- ここから
var name = "VARIABLE";
var obj = {
          name:"PROPERTY" ,
          age:25
          };

obj.getName_1 = function(){ trace( name );        }
obj.getName_2 = function(){ trace( this.name );   }
obj.getAge_1  = function(){ trace( age );         }
obj.getAge_2  = function(){ trace( this.age );    }

obj.getName_1(); // output : VARIABLE
obj.getName_2(); // output : PROPERTY
obj.getAge_1();  // output : undefined
obj.getAge_2();  // output : 25
// ---- ここまで

関数getName_1は、最初に定義した変数 name を参照していることが分かります。
一方、thisを指定したgetName_2は、きちんと自身のプロパティ name を参照しています。
また、getAge_1に至っては、参照先、age が見つけられずundefinedを返しています。
こちらもthisを付けて参照先を指定したgetAge_2では、意図した通り"25"を返しています。

このようにthisを使うのと使わないのとでは、大きく結果が異なってきます。

トラックバック(0)

このブログ記事を参照しているブログ一覧: デザイナーのためのActionScript講座 ― 第7回:続・オブジェクトと関数

このブログ記事に対するトラックバックURL: http://system.seyself.com/mt-tb.cgi/461

コメントする


画像の中に見える文字を入力してください。

しばらく時間が経過すると、システム内部と表示されている文字内容に食い違いが発生するようなので、
投稿する前にページをリロードすることをお勧めします。
リロードしてもフォームの内容は維持されます。