基本的な関数の概念

このセクションでは、基本的な関数の定義と呼び出し方法について説明します。

サブトピック

関数の呼び出し
独自の関数の定義
function ステートメント
関数式
ステートメントと式の選択
関数からの戻り値
ネストされた関数

関数の呼び出し

関数を呼び出すには、識別子の後に括弧 (()) を使用します。関数に渡す関数パラメータを括弧で囲みます。たとえば、Flash Player API の最上位関数である trace() 関数は、本マニュアルのさまざまな場所で使用されます。

trace("Use trace to help debug your script");

関数をパラメータなしで呼び出す場合、空の括弧のペアを使用する必要があります。たとえば、パラメータを取らない Math.random() メソッドは、乱数を生成します。

var randomNum:Number = Math.random();

独自の関数の定義

ActionScript 3.0 の関数を定義するには、function ステートメントを使用する方法と関数式を使用する方法の 2 つがあります。どちらの方法を選択するかは、プログラミングスタイルをより静的にするか動的にするかによって決まります。静的な、つまり strict モードのプログラミングの方を好む場合は、function ステートメントで関数を定義します。そうすることに特定の必要性がある場合は、関数式で関数を定義します。関数式は、動的、つまり standard モードのプログラミングでより頻繁に使用されます。

function ステートメント

function ステートメントは、strict モードで関数を定義するのに適しています。function ステートメントは、function キーワードで始まり、次のアイテムが続きます。

たとえば、次のコードは、パラメータを定義する関数を作成し、ストリング "hello" をパラメータ値として使用して関数を呼び出します。

function traceParameter(aParam:String)
{
    trace(aParam);
}

traceParameter("hello"); // hello

関数式

関数を宣言する 2 つ目の方法は、代入ステートメントに関数式を使用することです。関数式は、関数リテラルまたは匿名関数とも呼ばれます。これは、旧バージョンの ActionScript で広く使用されている、より冗長になる方法です。

関数式を持つ代入ステートメントは、var キーワードで始まり、次のアイテムが続きます。

たとえば、次のコードは関数式を使用して traceParameter 関数を宣言します。

var traceParameter:Function = function (aParam:String)
{
    trace(aParam);
};
traceParameter("hello"); // hello

function ステートメントとは異なり、関数の名前を指定していないことに注意してください。関数式が function ステートメントと異なるもう 1 つの特徴は、関数式はステートメントではなく式であることです。つまり、function ステートメントのように、関数式はそれだけでは成立しません。関数式は、通常は代入ステートメントなど、ステートメントの一部としてのみ使用することができます。次の例は、配列エレメントに代入された関数式を示します。

var traceArray:Array = new Array();
traceArray[0] = function (aParam:String)
{
    trace(aParam);
};
traceArray[0]("hello");

ステートメントと式の選択

原則として、式を使用する必要がある場合を除いて、function ステートメントを使用します。function ステートメントは、関数式より簡潔で、strict モードと standard モードで一貫した使いやすさを提供します。

function ステートメントは、関数式を含む代入ステートメントより読みやすくなります。function ステートメントを使用すると、コードが簡潔になり、varfunction キーワードを両方使用する必要がある関数式よりわかりやすくなります。

function ステートメントは、2 つのコンパイラモードで一貫した使いやすさを提供します。つまり、strict モードおよび standard モードの両方でドットシンタックスを使用し、function ステートメントを使用して宣言されたメソッドを呼び出すことができます。これは、関数式を使用して宣言されたメソッドには必ずしも当てはまりません。たとえば、次のコードは、2 つのメソッドで Example というクラスを定義します。関数式で宣言される methodExpression() と function ステートメントで宣言される methodStatement() です。strict モードでは、ドットシンタックスを使用して、methodExpression() メソッドを呼び出すことはできません。

class Example
{
  var methodExpression = function() {}
  function methodStatement() {}
}

var myEx:Example = new Example();
myEx.methodExpression(); // strict モードではエラー、standard モードでは OK
myEx.methodStatement(); // strict モードと standard モードで OK

関数式は、実行時、つまり動的なビヘイビアを中心にしたプログラミングに適しています。strict モードを使用し、関数式で宣言されるメソッドを呼び出す必要がある場合は、次の 2 つの方法のいずれかを使用することができます。1 つ目は、ドット (.) 演算子ではなく、角括弧 ([]) を使用してメソッドを呼び出す方法です。次のメソッドの呼び出しは strict モードと standard モードの両方で成功します。

myExample["methodLiteral"]();

2 つ目は、クラス全体をダイナミッククラスとして宣言することができます。この場合、ドット演算子を使用してメソッドを呼び出すことができますが、そのクラスのすべてのインスタンスで strict モードの一部の機能が犠牲になるという短所があります。たとえば、ダイナミッククラスのインスタンスの未定義のプロパティにアクセスしようとした場合、コンパイラはエラーを生成しません。

関数式が便利な場合があります。関数式の一般的な使用法は、1 回だけ使用された後で破棄される関数に使用することです。また、一般的な使用法ではありませんが、関数をプロトタイププロパティに関連付けるために使用します。詳細については、プロトタイプオブジェクトを参照してください。

function ステートメントと関数式には、どちらを使用するかを選択する際に考慮する必要がある微妙な違いが 2 つあります。1 つ目の違いは、関数式は、メモリ管理およびガベージコレクションに関してオブジェクトとして単独で存在しません。つまり、配列エレメントやオブジェクトプロパティなどの別のオブジェクトに関数式を割り当てると、コード内にその関数式への唯一の参照が作成されます。関数式が関連付けられている配列またはオブジェクトがスコープ外に移動するか、使用できなくなった場合、関数式にアクセスできなくなります。配列またはオブジェクトが削除されると、関数式が使用するメモリがガベージコレクションの対象となります。つまり、メモリは他の目的で再要求され、再利用される対象となります。

次の例では、関数式の場合、関数式が割り当てられているプロパティが削除されると、関数が利用できなくなることを示します。クラス Test は動的です。つまり、関数式を保持する functionExp というプロパティを追加できます。functionExp() 関数は、ドット演算子を使用して呼び出すことができますが、functionExp プロパティが削除されると、関数にアクセスできなくなります。

dynamic class Test {}
var myTest:Test = new Test();

// 関数式
myTest.functionExp = function () { trace("Function expression") };
myTest.functionExp();   // 関数式
delete myTest.functionExp;
myTest.functionExp();   // エラー

その一方で、関数が最初に function ステートメントで定義された場合、関数はそのオブジェクトとして存在し、関連付けられているプロパティを削除しても存在します。delete 演算子はオブジェクトのプロパティでのみ動作するので、関数 stateFunc() 自体を削除する呼び出しであっても動作しません。

dynamic class Test {}
var myTest:Test = new Test();

// function ステートメント
function stateFunc() { trace("Function statement") }
myTest.statement = stateFunc;
myTest.statement(); // function ステートメント
delete myTest.statement;
delete stateFunc;   // 無効
stateFunc();        // function ステートメント
myTest.statement(); // エラー

function ステートメントと関数式の 2 つ目の違いは、function ステートメントは、関数ステートメントの前に現れるステートメント内を含む、定義されたスコープ全体で存在することです。対照的に、関数式はそれ以降のステートメントに対してのみ定義されます。たとえば、次のコードは、定義される前に scopeTest() 関数を正常に呼び出します。

statementTest(); // statementTest

function statementTest():void
{
    trace("statementTest");
}

関数式は定義されるまで使用できないので、次のコードはランタイムエラーを発生します。

expressionTest(); // ランタイムエラー

var expressionTest:Function = function ()
{
    trace("expressionTest");
}

関数からの戻り値

関数から値を返すには、return ステートメントの後に、返す式またはリテラル値を使用します。たとえば、次のコードは、パラメータを表す式を返します。

function doubleNum(baseNum:int):int
{
    return (baseNum * 2);
}

return ステートメントは関数を終了させるので、次のように return ステートメントの下にあるステートメントは実行されないことに注意してください。

function doubleNum(baseNum:int):int {
    return (baseNum * 2);
    trace("after return"); // この trace ステートメントは実行されない
}

strict モードでは、戻り値の型を指定するように選択した場合、適切な型の値を返す必要があります。たとえば、次のコードは有効な値を返さないので、strict モードではエラーが発生します。

function doubleNum(baseNum:int):int
{
    trace("after return");
}

ネストされた関数

関数をネスト、つまり別の関数内で関数を宣言することができます。ネストされた関数は、関数への参照が外部コードに渡される場合を除いて、その親関数内でのみ使用できます。たとえば、次のコードは getNameAndVersion() 関数内に 2 つのネストされた関数を宣言します。

function getNameAndVersion():String
{
    function getVersion():String
    {
        return "9";
    }
    function getProductName():String
    {
        return "Flash Player";
    }
    return (getProductName() + " " + getVersion());
}
trace(getNameAndVersion()); // Flash Player 9

ネストされた関数が外部コードに渡される場合、関数クロージャとして渡されます。つまり、関数が定義されるとき、スコープ内にある定義を保持します。詳細については、関数クロージャを参照してください。


 

このページに新しいコメントが追加された場合に、電子メールでの通知を希望する。 | コメントレポート

現在のページ: http://livedocs.adobe.com/flash/9.0_jp/main/00000054.html