新JavaScript入門  JavaScript,Neo-Generation  DOM  WSH  掲示板  表紙
3.GUI部品  5.配列(1) 
新JavaScript入門
4. サブルーチン
関数オブジェクトの定義
サブルーチンは関数オブジェクトという形で提供されます。
関数オブジェクトは次のように定義されます。
    function functionname([arg1[, arg2[, ...]]]) {
        ...
    }
 
次のような定義の方法もあります。
    var functionname = function([arg1[, arg2[, ...]]]) {
        ...
    }
 
あと、newを使う方法もあります。
呼び出し方は次のようです。
    functionname([arg1[, arg2[, ...]]]);
 
値を返す
値を返すときは、 return で返します。
    function square(x) {
        return x * x;    //2乗して返す
    }
 
また、値を返さないときも return でサブルーチンから抜けられます。
引数
引数は値渡しです。
    function test1(form) {
        //テキストボックスに入力した数字
        var n = parseInt(form.text1.value);
        twice(n);           //2倍する操作は反映されない
        alert(n);           //結局表示は変わらない
    }
    
    function twice(a) {
        a *= 2;             //引数を2倍に
    }
 
    function test2(form) {
        var str = form.text1.value;
        hitomebore(str);
        alert(str);
    }
    
    function hitomebore(a) {
        a = "☆☆" + a + "にひとめぼれ☆☆";
    }
 
ただし、オブジェクト型は参照渡しです(値を渡してどーする)。
    function test3(form) {
        var p;
        p = new person("さくら", 9);   //person型オブジェクトを作る
        birthday(p);                    //歳を1つとる
        alert(p.name + " " + p.age + "歳");
    }
    
    //person型の定義
    function person(name, age) {
        this.name = name;
        this.age = age;
    }
    
    function birthday(a) {
        a.age++;
    }
 
このように、 JavaScript では新たにオブジェクトを作ることができます (そのうち詳しく説明します)。
サブルーチンに参照で引数を渡したいのは複数の値を返して欲しい時かと思いますが、 そういう場合は、このようにオブジェクトを引数にするか、 あるいは配列 は実はオブジェクトなので配列を引数にすればよいです。
文字列についてはここ も参照してください。
可変個の引数
引数の数を任意にしたい場合、例えば次のようにします。
    function test5() {
        alert(max(5, 1, 4, 0));
    }
    
    //引数の中から最大値を返す
    function max() {
        var n, result;
        //引数がなければnullを返す
        if((n = max.arguments.length) == 0)
            return null;
        result = max.arguments[0];
        for(var i = 1; i < n; i++) {
            if(max.arguments[i] > result)
                result = max.arguments[i];
        }
        return result;
    }
 
functionname.arguments として、 引数を要素とする配列を取り出すことができます。
再帰呼び出し
サブルーチンを再帰的に呼び出すことも可能です。 次はクイックソート[1]での例です。
    function test4(form) {
        var a, str, n, l, i, front, end;
        
        str = form.text1.value;
        l = str.length;
        
        //カンマの数をカウント
        n = 0;
        for(i = 1; i < l - 1; i++)
            if(str.charAt(i) == ",")
                n++;
        
        //カンマで区切られた数字を配列aに格納
        a = new Array(n + 1);
        i = front = 0;
        for(end = 1; end < l - 1; end++)
            if(str.charAt(end) == ",") {
                a[i++] = parseFloat(str.substring(front, end));
                front = end + 1;
            }
        a[i] = parseFloat(str.substring(front, l));
        
        quicksort(a, 0, n);         //クイックソート
        
        //ソートした結果を表示する
        str = "" + a[0];
        for(i = 1; i <= n; i++)
            str += "," + a[i];
        form.text1.value = str;
    }
    
    function quicksort(a, first, last) {
        var i, j, x, t;
        
        x = a[Math.floor((first + last) / 2)];
        i = first; j = last;
        for( ; ; ) {
            while(a[i] < x) i++;
            while(x < a[j]) j--;
            if(i >= j) break;
            t = a[i]; a[i] = a[j]; a[j] = t;
            i++; j--;
        }
        if(first < i - 1)
            quicksort(a, first, i - 1);    //再帰的呼び出し
        if(j + 1 < last)
            quicksort(a, j + 1, last);     //再帰的呼び出し
    }
 
数字をカンマ(,)で区切ってテキストボックスに入力してボタンを押してください。 数字が昇順でソートされます。
このように再帰的呼び出しも普通にできますが、 もちろん無制限にできるというわけではありません。 ある例で行ったらIEで329回、NNで998回の再帰的呼び出しが可能でした。

Functionオブジェクトを参照する
次のようにFunctionオブジェクトを参照することによって、 汎用性の高いスクリプトを書くことなどができます。
    function test6() {
        alert(integral(f1, 0, 1));
        alert(integral(f2, 0, 1));
    }
    
    function integral(f, x0, x1) {
        var result, i, dx;
        if(x0 == x1)
            return 0;
        dx = (x1 - x0) / 100;
        result = f(x0) + f(x1) + 4 * (f(x1-dx));
        for(i = 1; i < 99; i += 2)
            result += 4 * f(x0+dx*i) + 2 * f(x0+dx*(i+1));
        result *= (x1 - x0) / 300;
        return result;
    }
    
    function f1(x) { return x; }
    function f2(x) { return x * x; }
 

上はintegralという関数に関数を引数として渡しています。 integralはx0からx1まで積分した値を返します。 なんとかの公式という2次関数で近似するやつです。 高校で習いましたよね。
静的変数を使う
次のように静的変数を使うことができます(11/16/02)。
    function test7() {
        alert(test8(1));    //1
        alert(test8(2));    //2
    }
    
    function test8(x) {
        if(x == 1)
            this.a = 1;  //最初はこっち
        else
            this.a++;    //次からはこっち
        return this.a;
    }
 
this.a が静的変数で、サブルーチンを抜けても値を保持します。 this は test1 としてもよいです。
  [1] 奥村晴彦著 C言語による最新アルゴリズム事典 1991 技術評論社
 
Written 10/2/97
Modified 11/16/02
Modified 3/29/03
first, prev, next, exit