第10話:関数

第1部 JavaScriptプログラミングの基本

目次

マンガ

マンガ

マンガ

マンガ

マンガ

マンガ

マンガ台詞

【1Page】
アイコン遊:うー ぐー あー
アイコン守:どうしたの 遊ちゃん?
アイコン遊:私もだいぶ プログラムの達人に なってきたじゃない
    最近ソースが 長くなって 大変なのよ
    それに 同じような処理が 何度もあるし
    はーっ 面倒くさいわ もっと楽をしたいわ
アイコン先生:素晴らしい さすが手抜きの女王 遊くんだ!
    君は プログラマーの 素質がある
【2Page】
アイコン守:アイコン麗:ええっ!
アイコン先生:プログラムには 何度も行う処理を 一度だけ書いて済ませる 方法がある
    それが『関数』だ
    では 『関数』の 書き方を示すぞ
        function 関数名(引数) {
            内部処理
            return 戻り値;
        }
    引数や戻り値は なくても構わない
        function 関数名() {
            内部処理
        }
【3Page】
アイコン遊:『関数』?
    また変なのが出てきたわね
アイコン先生:『function』の内部処理は 『if』や『for』と違って すぐには実行されない
        if (~) {
            『すぐに実行』
        }
        for (~) {
            『すぐに実行』
        }
        function 関数名(~) {
            『関数名が書かれた
            別の場所で実行』
        }
    プログラムの 別の場所で 関数名が書かれた時に 中身が実行される
    また その際 『引数』を受け取ったり 『戻り値』を戻したり できる
        var kekka = han(16);

        function han(no) {
            var res = no / 2;
            return res;
        }
アイコン遊:複雑ね…
【4Page】
アイコン先生:例を書いてみよう 処理の順番を 数字で書くから 見てくれ
        01  var mojiretu;   // 変数の初期化

        // 【関数呼び出し】
        // 『関数』の『戻り値』を、変数『mojiretu』に入れる
        02  mojiretu = getMojiretu("足立", 65);

        03  alert(mojiretu);      // アラート表示

        // 【関数】(呼び出されるまで実行されない)
        // 第1『引数』を、変数『namae』に入れて受け取る
        // 第2『引数』を、変数『tennsuu』に入れて受け取る
        function getMojiretu(namae, tennsuu) {
            3.1, 4.1  var result = namae + "の点数は"
                        + tennsuu + "です";
            // 『戻り値』(関数の結果)を戻す
            3.2, 4.2  return result;
        }

        // 【関数呼び出し】
        // 『関数』の『戻り値』を、変数『mojiretu』に入れる
        04  mojiretu = getMojiretu("木村", 43);

        05  alert(mojiretu);      // アラート表示
    関数は 呼び出される前に 書いても 後に書いてもよい
    『足立の点数は65です』
    『木村の点数は43です』
    と、2つのダイアログが 表示される
【5Page】
アイコン麗:『alert』と使い方が 似ていますね
アイコン先生:ああ 『alert』も 『関数』だ
    『関数』は こういう風に 処理をまとめて あとで使えるように したものだ
アイコン遊:この方法で 何度も出てくる部分を まとめればよいのね?
アイコン先生:そうだ
    一度書いたプログラムは 『関数』にして 再利用する
    可能な限り 仕事をしないのが プログラムの基本だ
アイコン遊:素晴らしい考え方だわ

説明

この章では、『関数』について学びます。プログラムを書いていると、次第に行数が増えて、どこに何を書いているのか見づらくなってきます。そして、同じ処理を、何度も書かなければならなくなってきます。そういった時に利用するのが『関数』です。

『関数』は、何度も行う処理を、一度だけ書いて済ませるプログラムの書き方です。この方法を使えば、プログラムをいくつかの部品に分けて、組み立てるようにしてプログラムを書くことができます。

これは、自動車などの工業製品を作る手法と同じです。タイヤ、ハンドル、エンジン、ブレーキなどをばらばらに作り、最後に組み立てて完成させる。プログラムでも同じように、データを初期化する『関数』、データを加工する『関数』、画面に結果を表示させる『関数』などのように部品分けをして作り、それらの『関数』を組み合わせることで、プログラムを完成させることができます。

このような方法で『関数』を利用すると、プログラムの再利用性も向上します。以前書いたプログラムから、『関数』だけを持ってきて、新しいプログラム内で利用するといったことも可能になります。

それでは以下、『関数』について説明していきます。

『関数』の基本

『関数』は、以下の方法で作れます。

function 関数名(引数) {
    内部処理
    return 戻り値;
}

実際に、この書式で『関数』を作ってみましょう。

function han(no) {
    var res = no / 2;
    return res;
}

以下、このプログラムを元に、『関数』の構造について解説していきます。

『関数名』『引数』

『han』というのが『関数名』になります。『han』のあとの括弧内に書かれた『no』が、『引数』(ひきすう)と呼ばれる変数になります。『引数』は、内部処理を行う際に、外部から値を受け取るための変数です。

『引数』を書く括弧の中には、変数名を書きます。引数が必要ないのなら、何も書かなくても構いません。『引数』を複数使いたい場合は『han(no1, no2)』のように『,』(カンマ)で区切って並べて書きます。宣言した『引数』は、『関数』内でのみ有効です。

『内部処理』

続く『var res = no / 2;』というのが、内部処理になります。先ほど『引数』として宣言した『no』が計算式中で利用されているのが分かります。この内部処理は、ここでは1行しか書いていませんが、数行にわたって書くこともできます。

『return 戻り値』

最後の行の『return res;』については、少し詳しく説明します。『return』は、「ここで『関数』を終了する」という宣言です。『関数』内で『return』の書かれた行が実行されると、その場所で『関数』の処理が終了します。『関数』が終了すると、その『関数』が呼び出された場所まで処理が戻ります。

『関数』は、『{~}』の末尾まで来るか、『return』の行まで来ると、処理を終えて、呼び出された場所に戻ります。『関数』は、プログラムのどこに書いても構いません。呼び出される場所の前に書いてもよいですし、後に書いてもよいです。

『return』の後には、『関数』の『戻り値』を設定することができます。上記のプログラムでは、『戻り値』として『res』の値を設定しています。そのため、『関数』の結果として『res』の値が、呼び出された場所に戻ります。

『関数』の利用

作成した『関数』は、以下のように利用できます。

var kekka = han(16);

関数『han』を、引数『16』で呼び出しています。関数『han』の内部処理は『16÷2』で、戻り値は『8』となります。この『戻り値』は、『han(16)』という場所に戻されます。結果として、変数『kekka』には『8』という値が入ります。

また、『関数』は、変数のように、式の中に利用することもできます。

var kekka = han(16) * 2;

この場合、関数『han』の結果は『8』。その数字に『2』を掛けた値が、変数『kekka』に入ります。この場合の変数『kekka』の値は16になります。

参考

以下、中級者以上向け。

マンガ中のプログラムの解説

それでは、もう少し長い処理を見てみましょう。マンガで登場したプログラムを元にして、解説を行っていきます。

まず最初にプログラムを書き、その後、処理順番に並べ変えた内容を示します。

var mojiretu;   // 変数の初期化

// 【関数呼び出し】
// 『関数』の『戻り値』を、変数『mojiretu』に入れる
mojiretu = getMojiretu("足立", 65);

alert(mojiretu);      // アラート表示

// 【関数】(呼び出されるまで実行されない)
// 第1『引数』を、変数『namae』に入れて受け取る
// 第2『引数』を、変数『tennsuu』に入れて受け取る
function getMojiretu(namae, tennsuu) {
    var result = namae + "の点数は" + tennsuu + "です";
    return result;      // 『戻り値』(関数の結果)を戻す
}

// 【関数呼び出し】
// 『関数』の『戻り値』を、変数『mojiretu』に入れる
mojiretu = getMojiretu("木村", 43);

alert(mojiretu);      // アラート表示

以下、処理順番に並べ替えたものです。関数『getMojiretu』内の変数には青文字で、中身の値を書いておきます。

var mojiretu;   // 変数の初期化
mojiretu = getMojiretu("足立", 65);

function getMojiretu(namae"足立", tennsuu65) { var result = namae"足立" + "の点数は" + tennsuu65 + "です"; return result"足立の点数は65です"; // 『戻り値』(関数の結果)を戻す }
alert(mojiretu); // アラート表示『足立の点数は65です』 mojiretu = getMojiretu("木村", 43);
function getMojiretu(namae"木村", tennsuu43) { var result = namae"木村" + "の点数は" + tennsuu43 + "です"; return result"木村の点数は43です"; // 『戻り値』(関数の結果)を戻す }
alert(mojiretu); // アラート表示『木村の点数は43です』

それでは以下、さらに詳しく『関数』についてみていきましょう。

『関数』のいろいろな作り方

『関数』は、以下の方法で作れると紹介しました。

function 関数名(引数) {
    内部処理
    return 戻り値;
}

『関数』の作り方には、他にもいくつかの種類があります。

たとえば、『引数』を持たない『関数』は、以下のように書きます。

function 関数名() {
    内部処理
    return 戻り値;
}

また、『return』に何も値を指定しなかった場合は、『戻り値』を戻さない『関数』になります。

function 関数名(引数) {
    内部処理
    return;
}

『戻り値』を戻さない『関数』ならば、『return』自体を省略することもできます。

function 関数名(引数) {
    内部処理
}

『引数』も『戻り値』もない『関数』も作れます。

function 関数名() {
    内部処理
}

少し複雑な『関数』の実例

『return』を使った『関数』の途中終了を利用して、少し複雑な『関数』を作ってみます。以下のように、『引数』の値によって、処理を分岐させれば、より有用な『関数』を作成することができます。また、『引数』が想定内の値かどうかをチェックすることで、エラーを防ぐこともできます。

var kekka1 = menseki(0, 10);    // 関数『menseki』を呼び出し
var kekka2 = menseki(5, 10);    // 関数『menseki』を呼び出し
var kekka3 = menseki(10, 10);   // 関数『menseki』を呼び出し

document.write(kekka1 + "<br>");
document.write(kekka2 + "<br>");
document.write(kekka3 + "<br>");

function menseki(width, height) {
    // 『width』(横幅)を引数1として取得
    // 『height』(高さ)を引数2として取得

    if ((width <= 0) || (height <= 0)) {
        // 横幅か高さが0以下なら、面積は求められないので終了
        return "error!";
    }

    var res = width * height;
    return res;     // 計算結果を戻して終了
}

【結果】

error!
50
100

『if ((width <= 0) || (height <= 0))』として、横幅と高さの値が『0以下の数』にならないように確認しています。そして、どちらかが『0以下の数』だった場合は、『error!』という文字列を、戻り値として戻すようにしています。

このように処理を分岐させることで、複雑な『関数』を作ることができます。

『再帰関数』

以下、少し高度なことを説明します。

『関数』には、『再帰関数』と呼ばれるものがあります。『再帰関数』とは、『関数』から『それ自身を呼び出す』関数のことです。

以下、例を示します。

// 再帰関数を呼び出し
saiki(0, 12);

// 再帰関数
function saiki(no, max) {
    // 『no』(再帰回数)を引数1として取得
    // 『max』(終了条件の値)を引数2として取得

    // 終了条件を満たせば終了
    if (no >= max) return;

    // グラフの作成
    var str = "";
    for (var i = 0; i < no; i ++) {
        for (var j = 0; j <= i; j ++) {
            str += "+";
        }
    }
    document.write(str + no + "<br>");

    // 再び自分自身を呼び出す
    saiki(no + 1, max);
}

【結果】

0
+1
+++2
++++++3
++++++++++4
+++++++++++++++5
+++++++++++++++++++++6
++++++++++++++++++++++++++++7
++++++++++++++++++++++++++++++++++++8
+++++++++++++++++++++++++++++++++++++++++++++9
+++++++++++++++++++++++++++++++++++++++++++++++++++++++10
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++11

『再帰関数』は、終了条件を正しく設定していないと、『無限ループ』(無限に続いて終わらない処理)になることがあります。気を付けてください。

参考

サンプルの入手

以下は、今回出てきたサンプルです。

ZIPでまとめてダウンロード (右クリックから保存してください)

sample1.html』(処理の順番)を表示

sample2.html』(少し複雑な関数の実例)を表示

sample3.html』(再帰関数)を表示

プログラムの中身を見たい場合は、それぞれのHTMLファイルをブラウザで開いたあと、右クリックをして『ソースの表示』を選択してください。

メモ帳で、ファイルの中身を見ることができます。