| ActionScript 3.0 のプログラミング > ActionScript プログラミングの概要 > ActionScript 言語とシンタックス > 関数 > 関数のパラメータ | |||
ActionScript 3.0 は、ActionScript を初めて使用するプログラマには斬新な関数パラメータの機能を備えています。値または参照によってパラメータを渡すという概念は、ほとんどのプログラマにとってなじみがありますが、arguments オブジェクトおよび ... (rest) パラメータは初めて見るという人も多いかもしれません。
多くのプログラミング言語では、値渡しと参照渡しによるパラメータの受け渡しの違いを理解しておくことが重要です。この違いは、コードの設計方法に影響します。
値渡しとは、関数内で使用するためにパラメータの値がローカル変数にコピーされることです。参照渡しとは、実際の値ではなく、パラメータへの参照のみが渡されることです。実際の値がコピーされるのではなく、パラメータとして渡される、変数への参照が作成され、関数内で使用するためにローカル変数に割り当てられます。関数の外部にある変数への参照として、ローカル変数では元の変数の値を変更できます。
ActionScript 3.0 では、値はすべてオブジェクトとして格納されているため、すべてのパラメータは参照渡しです。しかし、Boolean、Number、int、uint、String などのプリミティブデータ型に属するオブジェクトには、値渡しのように動作する特別な演算子があります。たとえば、次のコードは、xParam と yParam という 2 つの int 型パラメータを定義する passPrimitives() という関数を作成します。この 2 つのパラメータは、passPrimitives() 関数の本体内で宣言されるローカル変数に似ています。関数がパラメータ xValue および yValue で呼び出されると、パラメータ xParam および yParam は、xValue と yValue で表される int オブジェクトへの参照で初期化されます。パラメータはプリミティブなので、値渡しのように動作します。xParam および yParam は、最初は xValue および yValue オブジェクトへの参照のみを含みますが、関数の本体内の変数を変更すると、メモリに値の新しいコピーが生成されます。
function passPrimitives(xParam:int,yParam:int):void {xParam++;yParam++; trace(xParam,yParam); } var xValue:int = 10; var yValue:int = 15; trace(xValue, yValue); // 10 15 passPrimitives(xValue, yValue); // 11 16 trace(xValue, yValue); // 10 15
passPrimitives() 関数内では、xParam および yParam の値はインクリメントされますが、最後の trace ステートメントに示されているように、これは xValue および yValue の値に影響を与えません。パラメータが変数 xValue および yValue と同じ名前である場合でも同じです。これは、関数内の xValue および yValue は関数の外部にある同じ名前の変数とは別に存在するメモリ内の新しい位置を参照するためです。
プリミティブデータ型に属していない他のすべてのオブジェクトは常に参照渡しによって渡されます。これにより、元の変数の値を変更できます。たとえば、次のコードは、2 つのプロパティ x および y を持つ objVar というオブジェクトを作成します。このオブジェクトは、passByRef() 関数にパラメータとして渡されます。オブジェクトはプリミティブ型ではないため、参照渡しで渡されるだけではなく、参照のままでもあります。つまり、関数内のパラメータを変更すると、関数の外側にあるオブジェクトのプロパティも影響を受けます。
function passByRef(objParam:Object):void
{
objParam.x++;
objParam.y++;
trace(objParam.x, objParam.y);
}
var objVar:Object = {x:10, y:15};
trace(objVar.x, objVar.y); // 10 15
passByRef(objVar); // 11 16
trace(objVar.x, objVar.y); // 11 16
objParamobjParam パラメータは、グローバル変数 objVar と同じオブジェクトを参照します。この例の trace ステートメントからもわかるように、objParam オブジェクトの x および y プロパティを変更すると、objVar オブジェクトにも反映されます。
ActionScript 3.0 では、関数のデフォルトのパラメータ値を宣言する機能が新しく追加されました。デフォルトのパラメータ値を使用した関数の呼び出しでデフォルト値のパラメータが省略されると、そのパラメータの関数定義で指定された値が使用されます。デフォルト値のパラメータはすべてパラメータリストの末尾に配置する必要があります。デフォルト値として割り当てられた値はコンパイル時定数である必要があります。パラメータのデフォルト値が存在すると、そのパラメータは "オプションパラメータ" になります。デフォルト値のないパラメータは、必須パラメータと見なされます。
たとえば、次のコードは、3 つのパラメータで関数を作成します。このうち、2 つのパラメータにはデフォルト値があります。パラメータ 1 つだけで関数を呼び出す場合、そのパラメータのデフォルト値が使用されます。
function defaultValues(x:int, y:int = 3, z:int = 5):void
{
trace(x, y, z);
}
defaultValues(1); // 1 3 5
パラメータが関数に渡されると、arguments オブジェクトを使用して関数に渡されたパラメータについての情報にアクセスできます。arguments オブジェクトには、次のような重要な特性があります。
arguments オブジェクトは、関数に渡されるすべてのパラメータを含む配列です。arguments.length プロパティは、関数に渡されるパラメータの数を報告します。arguments.callee プロパティを使用すると、関数自体を参照することができます。これは関数式の再帰呼び出しに便利です。|
メモ |
|
パラメータに |
ActionScript 3.0 では、関数呼び出しで関数定義内で定義されているパラメータより多いパラメータを指定できますが、パラメータ数が必須パラメータ数より少ない場合は strict モードでコンパイラエラーが生成されます。arguments オブジェクトの配列を使用すると、関数に渡されるパラメータが関数定義内で定義されたかどうかに関わらず、このパラメータにアクセスできます。次の例では、arguments 配列と arguments.length プロパティを使用して、traceArgArray() 関数に渡されるすべてのパラメータをトレースします。
function traceArgArray(x:int):void
{
for (var i:uint = 0; i < arguments.length; i++)
{
trace(arguments[i]);
}
}
traceArgArray(1, 2, 3);
// 出力 :
// 1
// 2
// 3
arguments.callee プロパティは、再帰を作成する場合に匿名関数でよく使用されます。このプロパティを使用すると、コードに柔軟性を持たせることができます。開発過程で再帰関数の名前が変更された場合でも、関数名ではなく arguments.callee を使用していれば、関数本体内の再帰呼び出しの変更について考慮する必要はありません。次の関数式で arguments.callee プロパティを使用して再帰を有効にします。
var factorial:Function = function (x:uint)
{
if(x == 0)
{
return 1;
}
else
{
return (x * arguments.callee(x - 1));
}
}
trace(factorial(5)); // 120
関数宣言で ... (rest) パラメータを使用する場合は、arguments オブジェクトを使用することはできません。代わりに、宣言したパラメータ名を使用してパラメータにアクセスする必要があります。
ストリング "arguments" をパラメータ名として使用しないようにする必要があります。このストリングは arguments オブジェクトをシャドウするためです。たとえば、関数 traceArgArray() が arguments パラメータが追加されるように記述し直されると、関数本体内の arguments への参照は、arguments オブジェクトではなく、このパラメータを参照します。次のコードは出力を作成しません。
function traceArgArray(x:int, arguments:int):void
{
for (var i:uint = 0; i < arguments.length; i++)
{
trace(arguments[i]);
}
}
traceArgArray(1, 2, 3);
// 出力なし
旧バージョンの ActionScript の arguments オブジェクトには、caller という名前のプロパティも含まれていました。これは、現在の関数を呼び出した関数への参照です。ActionScript 3.0 には caller プロパティはありません。しかし、呼び出し元の関数への参照が必要な場合は、それ自体への参照である追加のパラメータを渡すように呼び出し元の関数を変更することができます。
ActionScript 3.0 では、... (rest) パラメータと呼ばれる新しいパラメータ宣言が導入されました。このパラメータを使用すると、任意の数のカンマ区切りのパラメータを受け入れる配列パラメータを指定できます。パラメータには、予約語ではない名前を指定することができます。このパラメータ宣言は、指定される最後のパラメータである必要があります。このパラメータを使用すると、arguments オブジェクトは使用できなくなります。... (rest) パラメータには arguments 配列および arguments.length プロパティと同じ機能がありますが、arguments.callee のような機能はありません。... (rest) パラメータを使用する前に、arguments.callee を使用する必要はありません。
次の例では、arguments オブジェクトではなく、... (rest) パラメータを使用して traceArgArray() 関数を記述し直します。
function traceArgArray(... args):void
{
for (var i:uint = 0; i < args.length; i++)
{
trace(args[i]);
}
}
traceArgArray(1, 2, 3);
// 出力 :
// 1
// 2
// 3
... (rest) パラメータは、パラメータリストの最後のパラメータであれば、他のパラメータと使用することもできます。次の例では、traceArgArray() 関数を変更して、最初のパラメータ x を int 型にし、2 つ目のパラメータが ... (rest) パラメータを使用するようにします。最初のパラメータは ... (rest) パラメータにより作成された配列の一部ではなくなるため、最初の値は出力されません。
function traceArgArray(x: int, ... args)
{
for (var i:uint = 0; i < args.length; i++)
{
trace(args[i]);
}
}
traceArgArray(1, 2, 3);
// 出力 :
// 2
// 3
Flex 2.01