Chap01 プログラミングの基礎知識の最近のブログ記事

(section01-03 フレームアクションのメソッド定義と関数定義から抜粋)

 関数のネスティング(入れ子で定義する)も可能です。次の例はgetUser関数の中にgetID関数とgetName関数が定義されています

[:script:]関数の中に関数を入れ子で定義する
function getUser():Array { 
	var domain:String = "jq1";
    function getID():String { 
        return domain+"abc"; 
    } 
    function getName():String { 
        return "大重美幸"; 
    } 
    return ([getID(),getName()]); 
} 
//テスト
trace(getUser());//出力:jq1abc,大重美幸
 関数をネスティングする利点には、親関数getUser()のローカル変数の値をネストされた子関数getID()が利用できることがあります。このような形態を関数クロージャ(function closure)あるは関数閉包と呼びます。関数クロージャが他の関数に引数として渡されたり、ほかの関数から呼び出された場合にも内部のローカル変数の値は保持されます。

note
関数クロージャではthisを正しく理解して使う必要があります。
var a:int=1;
trace(this, this.a, a);//出力:[object MainTimeline] 1 1
function test():void {
	var a:int=2;
	trace(this, this.a, a);//出力:[object MainTimeline] 1 2
	closetest();
	function closetest():void {
		trace(this, this.a, a);//出力:[object global] undefined 2
	}
}
//テスト
test();
(section01-03 フレームアクションのメソッド定義と関数定義から抜粋)

 関数はFunctionクラスのインスタンスの値として扱うことができることから、他の変数に代入したり引数として渡すことができます。たとえば、次のようにheikin3関数を定義したとき、heikin3を変数myTest(データ型:Function)に代入することでheikin3()をmyTest()で実行できるようになります。

[:script:]関数を変数の値に入れて使う
//3つの値の平均を求める
function heikin3(a:Number, b:Number, c:Number):Number {
	var abc:Number = a+b+c;
	var ans:Number = abc/3;
	return ans;
}
//関数を変数に代入する
var myTest:Function = heikin3;
var ans:Number = myTest(10, 20, 30);
trace(ans); //出力:20
(section01-03 フレームアクションのメソッド定義と関数定義から抜粋)

 中上級者向けの内容になりますが、関数を定義する方法には関数式を使うやり方もあります。関数式でもfunctionを使って関数を定義しますが、関数名を指定しない点に注目してください。関数名がないことから関数式で定義した関数は匿名関数あるいは関数リテラルと呼ばれます。

関数式の書式:
var 変数:Function = function (引数:データ型, 引数:データ型, ...):戻す値のデータ型{
//実行するスクリプト
}

 次の匿名関数は引数の値を10倍した値を出力します。定義した匿名関数は、続く7行目で行っているように関数を代入した変数名にカッコを付けて、test(3)のように実行できます。

[:script:]値を10倍する匿名関数を定義する
var test:Function = function (a:Number):void{
	var ans:Number = a * 10;
	trace(ans);
};

//匿名関数を使う
test(3); //出力:30
 値を戻す匿名関数も定義できます。次の匿名関数は引数の値を10倍した値を返します。

[:script:]10倍した値を返す匿名関数を定義する
var test:Function = function (a:Number):Number{
	var ans:Number = a * 10;
	return ans;
};

var ans:Number = test(5);
trace(ans); //出力:50
(section01-03 フレームアクションのメソッド定義と関数定義から抜粋)

 同一のタイムライン内では同名の変数は1個しか宣言することが許されません。つまり、たとえ異なるキーフレームのフレームアクションでも変数名が同じならばそれは同じ変数であり同じ値が入っています。これをグローバル変数と呼びます。
 ところが、メソッドや関数を定義するfunctionブロックの内側で変数を宣言したとき、その変数は個別のfunctionブロックの中だけで利用できる変数になります。これをローカル変数と呼びます。
 functionブロックの中と外で同名の変数が定義してあるとき、functionブロックの外の変数はグローバル変数になり、functionの中で宣言した変数はローカル変数になります。もちろん名前の重複エラーになることもありません。
 次の例では変数aをfunctionの外で宣言しています。この場合、test1()、test2()のfunction内も含めて同一タイムラインにおいて変数aは共通のグローバル変数になります。

note
ムービークリップのタイムラインで定義してあるグローバル変数の値は、ムービークリップのインスタンスごとに保存されます。

[:script:]functionブロックの外で宣言するグローバル変数a
//変数aの宣言
var a:int=100;

function test1():void{
	//変数aに1加算する
	a += 1;
	trace(a);
}

function test2():void{
	//変数aを2倍する
	a *= 2;
	trace(a);
}

//テスト
test1(); //出力:101
test2(); //出力:202
trace(a); //出力:202
 一方、次の例では変数aをfunctionブロックの外だけでなく、test1()のfunctionブロックの中でも宣言して使っています。このとき、続くテストの結果を見るとわかるように、test2()で参照している変数aはブロックの外で宣言している変数aと同じ変数ですが、test1()の中で宣言してある変数aは名前が同じでもtest1()の中だけの変数、すなわちローカル変数であることがわかります。

[:script:]test1()ではローカル変数aを宣言して使う
//変数aの宣言
var a:int=100;

function test1():void{
	//ローカル変数aの宣言
	var a:int=5;
	//ローカル変数aに1加算する
	a += 1;
	trace(a);
}

function test2():void{
	//変数aを2倍する
	a *= 2;
	trace(a);
}

//テスト
test1(); //出力:6
test2(); //出力:200
trace(a); //出力:200
(section01-03 フレームアクションのメソッド定義と関数定義から抜粋)

 関数は次のようにfunctionで定義し、returnで演算結果を戻します。値はfunctionを呼び出した位置に戻ります。関数では演算に使用する値を引数で受け取ることができます。
 引数で受け取る値のデータ型と関数で戻す値のデータ型を指定できます。データ型の指定は省略可能ですが、データ型を指定することでコンパイル時にデータ型の妥当性がチェックされます。
 メソッドと同様に関数定義はタイムラインのキーフレームで行いますが、関数を定義してあるキーフレームを再生していなくても、同じタイムラインであればどこからでもその関数を利用できます。同一のタイムラインで同名の関数を定義することはできません。

書式:
function 関数名(引数:データ型, 引数:データ型, ...):戻す値のデータ型{
//実行するステートメント
return 戻す値;
}

次のheikin3()は引数で与えられた3つの数値の平均を求めて返す関数です。

[:script:]3つの値の平均を求める
function heikin3(a:Number, b:Number, c:Number):Number {
	var abc:Number = a+b+c;
	var ans:Number = abc/3;
	return ans;
}	
 次の例がheikin3()を使って3教科の点数の平均を求めた場合です。ここに示すようにheikin3(kokugo, sugaku, eigo)を実行して得られた値が変数heikintenに入ります。heikin3()で戻る値のデータ型をNumberに指定しているので、変数heikintenのデータ型と一致します。

[:script:]3教科の平均点を求める
var kokugo:uint = 76;
var sugaku:uint = 62;
var eigo:uint = 70;
var heikinten:Number = heikin3(kokugo, sugaku, eigo);
trace(heikinten); //出力:69.33333333333333
(section01-03 フレームアクションのメソッド定義と関数定義から抜粋)

 returnを実行することでメソッドの中の残りの処理を中断できます。returnは関数の中で値を戻すためのステートメントですが、メソッドの中では戻す値を指定せずに使用します。
 次のtest()は引数aが0のときは処理を中断します。このスクリプトでは2行目で条件分岐のif文を使っています。これによりaの値が0のときだけ4行目のreturnが実行され、続く6行目が実行されずにtest()が終了します。aの値が0でないときはif文で囲った中が実行されずに6行目が実行されます。

[:script:]引数が0のとき処理を中断する
function test(a:int):void {
	if(a==0){
		trace("中断");
		return;
	}
	trace(10/a);
}

test(0);//出力:中断
test(5);//出力:2
(section01-05 データ型から抜粋)

 関数の引数に渡す値がプリミティブ型なのかリファレンス型なのかにも注意が必要です。プリミティブ型の変数を引数として渡したときは、関数の中でその引数に対して操作しても元の変数には影響がでません。一方、リファレンス型の変数を関数の引数として渡した場合には、関数の中で引数の値を変更すると元の変数の値が変化してしまいます。

値渡し(プリミティブ型)
 次の例では価格と個数から金額を計算するkeisan()を使っています。keisan()では変数tankaの値を引数kakakuで受け、それに個数を掛けた値をそのままkakakuの値として上書きしてます。結果を見るとわかるように演算後の変数tankaの値は2400のまま変化していません。

[:script:]引数で渡した変数は変化しない
var tanka:int = 2400;
var kingaku:int = keisan(tanka, 2);
//結果を調べる
trace(tanka); //出力:2400
trace(kingaku); //出力:4800

//引数で渡された変数を使って計算する
function keisan(kakaku:int, kosu:int):int {
	kakaku = kakaku * kosu;
	return kakaku;
}

参照渡し(リファレンス型)
 次の例は最小値を調べるためにArray型の変数を引数で渡した結果、元の配列の並びが変化してしまう例です。Arrya型の変数pricesを作り、数字の並びを配列として代入します。8行目以降で定義してあるgetMin()は引数で受けとった配列の中の最小値を調べて返す関数です。このとき、getMin()は引数vlistで受けた配列の値をvlist.sort()を実行して直接並べ替えています。この結果、2行目が実行されると最小値が変数lowPriceに代入されるだけではなく、引数として与えたpricesの値の並びも変えてしまうことになります。

[:script:]引数で渡した変数に入っていた配列の並びが変化してしまう
var prices:Array = [20, 56, 12, 40];
var lowPrice:int= getMin(prices);
//結果を調べる
trace(prices); //12,20,40,56
trace(lowPrice); //12

//引数で渡された変数を使って計算する
function getMin(vlist:Array):int {
	//vlistをソートする
	vlist.sort();
	//1番目の値を返す
	return vlist[0];
}

(section01-03 フレームアクションのメソッド定義と関数定義から抜粋)

 引数の個数が決まっていない場合には、残りの引数を...restのように書いて変数restで受けることができます。restは変数名なので...vlist、...nokoriのように好きな変数名を使えます。引数の値は指定の変数に配列で入ります。
 次の例では引数はすべて変数vlistに配列で入ります。

[:script:]引数の個数を指定せず、すべて配列に入れる
function test(...vlist):void {
	//配列vlistの値を出力する
	trace(vlist);
}

//引数をテストする
test(10, 20, 30, 40);
//出力:10,20,30,40
 次の例では第1引数は変数aに入りますが、残りの引数はすべて変数restに配列で入ります。

[:script:]2個目以降の引数は配列に入れる
function test(a:String, ...rest):void {
	//引数の値を出力する
	trace(a);
	trace(rest);
}

//引数をテストする
test("色", "red", "green", "blue", "black");
 出力結果は次のようになります。変数aには"色"と入り、変数restには色の名前が配列で入ります。

出力結果:

red,green,blue,black
(section01-03 フレームアクションのメソッド定義と関数定義から抜粋)

 メソッドに引数を渡すことができます。引数にはデータ型を指定できます。次のスクリプトは、動かすインスタンスと移動距離を引数で指定できるようにmoveXメソッドを変更したものです。

[:script:]動かすインスタンスと距離を引数で指定する
//moveX()の定義
function moveX(mc:MovieClip, v:Number):void {
	mc.x = mc.x + v;
}

//moveX()を実行する
moveX(my_mc1, 150);
moveX(my_mc2, 200);
 このサンプルではmoveX()を2度実行しています。moveX(my_mc1, 150)ではmy_mc1を右へ150ピクセル移動させ、moveX(my_mc2, 200)ではmy_mc2を右へ200ピクセル移動させます。このように引数を使うことで同じような処理を1つのメソッドで実現できるようになります。
 メソッドに引数が指定してある場合、メソッドを実行する際に引数と同数の値を渡す必要があります。引数の個数が一致しない場合はエラーになります。また、引数のデータ型が一致しない場合もエラーになります。たとえば、次のようなケースではエラーになります。

[:script:]引数が一致せずにエラーになるケース
//moveX()の定義
function moveX(mc:MovieClip, v:Number):void {
	mc.x = mc.x + v;
}

//エラーになるケース
moveX(my_mc1);//引数の個数が合わない
moveX(my_mc2, 200, 15);//引数の個数が合わない
moveX("my_mc1", 200);//引数のデータ型が合わない

引数の省略と初期値
 メソッドの引数が省略されたときに初期値を指定することができます。引数に初期値を指定するには、「引数=初期値」のように指定します。次の例では引数a、bの初期値をそれぞれ1と10に設定しています。

[:script:]引数に初期値が設定してあるメソッド
function ab(a:int=1, b:int=10):void {
	trace(a+b);
}

//引数による結果の違いのテスト
ab();//出力:11
ab(5);//出力:15
ab(5,50);//出力:55
 引数を変えてテストした結果をみるとわかるように、初期値が設定してあれば引数の個数が不足してもエラーにはならず、省略した引数はその値に初期値が使用されます。  なお、引数に初期値が指定してあっても前の引数の値を省略することはできません。また、指定の引数の個数以上の引数を渡すとエラーになります。

[:script:]エラーになるケース
ab(, 30);//前の引数は省略できない
ab(5,6,7);//引数の個数が多い
 メソッドを定義する場合、複数の引数があるとき引数の省略は後ろから可能です。次の例では第2引数にのみ初期値を指定しているので、第2引数のみ省略可能になります。

[:script:]第2引数のみ省略可能
function ab(a:int, b:int=10):void {
	trace(a+b);
}

//引数による結果の違いのテスト
ab(5);//出力:15
ab(5,50);//出力:55

 次のように初期値を指定していない引数より前の引数に初期値を指定することはできません。

[:script:]前の変数の初期値だけ指定するとエラーになる
function ab(a:int=1, b:int):void {
	trace(a+b);
}

note関数の引数の値渡しと参照渡し」も参照してください。
(section01-03 フレームアクションのメソッド定義と関数定義から抜粋)

 スクリプトの中でよく利用する処理はfunctionを使ってメソッドとして定義することができます。メソッドでは処理に使用する値を引数で受け取ることができます。メソッドのデータ型は省略可能ですが、省略しない場合には必ずvoidを指定します。
 メソッド定義はタイムラインのキーフレームで行いますが、メソッドを定義してあるキーフレームを再生していなくても、同じタイムラインであればどこからでもそのメソッドを利用できます。同一のタイムラインで同名のメソッドを定義することはできません。

メソッドの書式:
function メソッド名(引数:データ型, 引数:データ型, ...):void{
//実行するスクリプト
}

 次のスクリプトはmy_mcを右へ200ピクセル移動させるmoveXメソッドを定義するスクリプトです。このメソッドには引数はありません。

[:script:]moveX()メソッドの定義
function moveX():void {
 my_mc.x = my_mc.x + 200;
}

 moveXメソッドはmoveX()で実行できます。

[:script:]moveX()の定義と実行
//moveX()の定義
function moveX():void {
	my_mc.x = my_mc.x + 200;
}	
	
//moveX()を実行する
moveX();
まったく新しいAS3の世界!
694a.jpg
Adobe Flash CS4
詳細!ActionScript3.0入門ノート[完全改訂版](CD-ROM付)

楽しいActionScript。
新たなる1歩へと踏み出しましょう。
■内容は?→ 目次を見る
■評判は?→ 書評を読む
この本を書いたわけ

このアーカイブについて

このページには、過去に書かれたブログ記事のうちChap01 プログラミングの基礎知識カテゴリに属しているものが含まれています。

次のカテゴリはChap03 配列とベクターと結合配列です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

あわせて読みたいブログパーツ