関数

 TJS2 の関数はサブルーチンとほぼ同義です。値を返すことのない場合も関数として扱います。
 また、特にクラスやオブジェクトのメンバとなっている関数を「メソッド」と呼ぶことがあります。

関数の書き方

 関数は、以下の書式で書くことができます。

    function 関数名 ( 引数リスト )
    {
        関数の内容
    }


 まず、関数を定義するには、function を書きます。そのあとに、関数の名前を書きます。ここに書いた名前で関数が使用可能になります。
 関数の内容には、関数内で実行したいステートメントやブロックを記述することができます。


例:
    function test(a) { System.inform(a); }
    function func(a, b, c, d)
    {
        test(a);
        test(b);
        test(c);
        test(d);
        return a+b-c*d;
    }


関数に対して instanceof 演算子を "Function" を伴って使用した場合は真になります(上記の例で言うと、func instanceof "Function" は真)。

関数の呼び出し

 関数の呼び出しは ( ) 演算子を使って、以下のように記述します。
    関数名( 引数 )
    引数がない場合は、関数名( ) になります。引数には、式を指定し、複数ある場合はカンマで区切って指定します。

例:
    func();
    func(1+2, 1-2);
    func(func2());


    また、式を指定せずに、空にしておくと、そこの部分には void が指定されたと見なされます。

例:
    func(,1); // void, 1 が指定されたとみなされる
    func(,); // void, void が指定されたと見なされる

引数リスト

 引数リストには、渡された引数を受け取るための変数の名前を書きます。関数呼び出しの際に渡した引数のうち、前に書いたものから順番に、変数に引き渡されます。

例:
    function test(a, b, c)
    {
        // この時点で、 a と b と c という変数が使用可能であり、
        // 引数として渡された 3 つの引数が代入されています。
        // test(1, 2, 3) と呼び出した場合は、 a に 1、
        // b に 2, c に 3 が入っています。
    }


 これらの引数はローカル変数であり、関数から実行が抜けるとアクセスできなくなります。

 TJS2 では、関数呼び出しの際に与えられた引数が宣言の引数の数よりも少なかったり、多かったりしてもエラーにはなりません ( 例外的に、TJS2 で記述されたのではない関数 ( 実体が C++ などで記述された関数 ) はエラーにする場合があります )。与えられた引数が宣言より多い場合は多い分が無視され、少ない場合は、足りない変数には void が渡されます。

例:
    function test(a, b)
    {
        // もし test(1) として呼び出すと、a には 1 、b には void が入る。
        // もし test(1,2,3) として呼び出すと、 a には 1、 b には 2 が入り、3 は無視される
    }


 引数リストの個々の引数には、 = に続けてデフォルトの値 ( デフォルト引数 ) を指定することができます。これは、void が指定されたときや、与えられた引数が宣言の引数に満たない場合に、自動的に指定された値が使用されるというものです。

例:
    function test(a = -1, b = 1)
    {
        // もし・・・
        // test() として呼び出すと、 a=-1, b=1
        // test(5) として呼び出すと、 a=5, b=1
        // test(void,void) として呼び出すと、 a=-1, b=1
        // test(,4) として呼び出すと、a=-1, b=4
    }


 引数を受け取る必要のない関数は、引数リストを省略することができます。

例:
    function test
    {
        // 引数を受け取らない関数
    }

式中関数

 function キーワードを式内で使うと、名前のない関数、式中関数 ( 匿名関数 ) を作成することができます。
 この場合、関数の名前は省略します。

例:
    var func = function(i) { return i*5; };
    var func2 = function { System.inform("hoge"); };
    var v = func(); // func 呼び出し
    func2(); // func2 呼び出し

引数の省略

 関数を呼び出す際に、 ... のみを引数として書くと、呼び出す式を記述した関数に引き渡された引数が、そのまま関数呼び出し先の関数に引き渡されます。これは、引数変数の内容を変更していても、あるいは受け取った引数が足りなくても、正しい元の内容、引数の数がわたります。

例:
    function test()
    {
        test2(...);
        // test2 には test に渡された引数が、渡された時点のまま
        // の内容、個数で渡される
    }

引数の配列変換

 引数を配列として受け取ることができます。配列として受け取るには、引数名に '*' を付けて関数を宣言します。

例:
    function func(args*)
    {
        // args はこの関数に渡された引数を要素として持つ配列になる
        // たとえば func(1, 2, 3, 4) として呼び出された場合、
        // args には 4 つの要素が入っており、先頭から 1 2 3 4 の順で
        // 数値が入っていることになる。
    }


 引数の途中から最後までを全て配列として受け取ることもできます。引数の数が満たなかった場合は、配列は空となります。

例:
    function func(x, args*)
    {
        // たとえば func(1, 2, 3, 4) として呼び出された場合、
        // x には 1 が入る。また args には 3 つの要素が入っており、
        // 先頭から 2 3 4 の順で数値が入っていることになる。
        // func(1) として呼び出された場合、引数の数が満たないため、
        // args は要素のない配列となる。
    }

 これは、可変長の引数を処理したい場合に便利です。

 引数名を指定しない事も可能です。この場合は、後述の配列の引数への展開の際に、名前なしの * として使用できます。

配列の引数への展開

 配列を展開し、引数として関数に渡すことができます。この場合は、引数の配列展開の際と同じく、展開したい式の後ろに '*' を付けて関数を呼び出します。'*' を指定して展開したい式は、配列を表して無ければなりません。

例:
    var args = [1, 2, 3, 4];
    func(args*);
    // args には 1 2 3 4 の4つの要素が入っているため、
    // func(1, 2, 3, 4); と同じ意味になる。
    func(0, args*, 5);
    // このように引数の途中に挟むことも可能。
    // この場合は、func(0, 1, 2, 3, 4, 5); と同じ意味に
    // なる。


 式を指定せずに、単に * を引数に指定すると、呼び出す式を記述した関数の宣言時に書いた名前のない '*' が表す引数を、そのまま呼び出し先に渡すことができます。
例:
    function func(func_array, *)
    {
        // func_array で指定された関数に、
        // その関数の func_array 内の位置につづき、
        // func に渡された 2 番目以降の引数を
        // そのまま引き渡して呼び出す
        for(var i = 0; i < func_array.count; i++)
            func_array[i](i, *);
    }


 名前の無い * による関数呼び出し処理は、名前のある配列を使うよりも効率よく処理できます。

例:
    function func(ar*) { func2(ar*); }
    function func(*) { func2(*); }
    // 上記の二つは全く同じ意味になるが、下の例の方が効率がよい


 名前の無い * は、「引数の省略」と同様の効果を持ちます。以下の二つの関数宣言は同じ意味になります。

例:
    function func() { func2(...); }
    function func(*) { func2(*); }