We're looking for a user researcher to understand the needs of developers and designers. Is this you or someone you know? Check out the post: https://mzl.la/2IGzdXS

このコースでの関数の学習を終えるために、最後に議論しておくべき大事なコンセプトがあります。それは戻り値です。関数によっては完了時に特定の値を返さないものもありますが、値を返すものも当然あります。それらの値が何であるか、どのようにカスタム関数に意味のある値を返させるのかについて理解することは重要です。これらについてすべてを以下で紹介します。

前提条件:

基本的なコンピューターリテラシー、基本的な HTML と CSS の知識、JavaScript初級レベルの知識関数の知識

目的:

関数の戻り値とその使い方を理解すること

戻り値とは?

戻り値は、その名が示すとおり関数の実行が完了した時に返される値です。戻り値についてそこまで意識してこなかったかもしれませんが、これまでに何度も戻り値を見てきているはずです。以下のコードを見てみましょう。

var myText = 'I am a string';
var newString = myText.replace('string', 'sausage');
console.log(newString);
// 文字列の replace() 関数は文字列を受け取り、
// 一方の部分文字列をもう一方の部分文字列に置き換え、
// 置き換えられた新しい文字列を返します。

最初の関数の記事で紹介したコードです。myText という文字列の replace() 関数を実行し、置換される部分文字列と置換する部分文字列の2つの引数を渡しています。この関数の実行が完了した時に、関数は置換された新しい文字列を値として返します。上記のコードでは、この戻り値を newString 変数に代入しています。

replace 関数についての MDN の解説ページには、Return value というセクションがあります。関数によって返される値が何か知り把握することはとても大事です。従って、可能な限りこちらも見るようにしてください。

関数によっては戻り値を返しません(この解説ページでは、このような場合 void または undefined として戻り値を記載しています)。たとえば、前の記事で作った displayMessage() function では、呼び出された関数の結果として特定の値は返されていません。ただスクリーンのどこかにボックスの表示を作っているだけです。

一般的に、戻り値は関数がある種の計算をしている途中の段階で使用されます。何らかの値を伴った最終的な結果に到達するために、これらの値は関数によって計算される必要があります。関数が結果を返すことによって、戻り値は次の計算の段階で使われるようになります。

オリジナル関数での戻り値の使い方

カスタム関数から値を返すために、必要なことは、return というキーワードを使うことです。直近の random-canvas-circles.html の例でこれを見田でしょう。draw() 関数は100 のランダムな円を HTML 内に表示します。
<canvas>:

function draw() {
  ctx.clearRect(0,0,WIDTH,HEIGHT);
  for (var i = 0; i < 100; i++) {
    ctx.beginPath();
    ctx.fillStyle = 'rgba(255,0,0,0.5)';
    ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI);
    ctx.fill();
  }
}

ループの繰り返しの中で、現在の円の x 座標、y 座標、半径それぞれのランダムな値を生成するために random() 関数に対して3 回の呼び出しが行われます。random() 関数はひとつの引数(整数)を受け取り、0 からその受け取った数値までの乱数を返します。以下のようになります。

function random(number) {
  return Math.floor(Math.random()*number);
}

次のように書くことも可能です。

function random(number) {
  var result = Math.floor(Math.random()*number);
  return result;
}

しかし最初のものの方がよりコンパクトで、効率よく書けています。

関数が呼び出されるたびに、Math.floor(Math.random()*number) の計算の結果が返されます。この戻り値は、関数が呼び出された時点で表示されますが、コードはそのまま続行されます。たとえば、以下のコードを実行したとします。

ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI);

この時、3つの random() がそれぞれ 500、200、35 と値を返した場合、このコードは実際には次のように実行されたことになります。

ctx.arc(500, 200, 35, 0, 2 * Math.PI);

コード上の関数の呼び出しがまず行われ、その戻り値が関数の呼び出しの代わりとなり、その後にコードそのものが実行されます。

実践: 戻り値を返す関数を作る

戻り値を返すオリジナルな関数を書いてみましょう。

  1. まず最初に GitHub から function-library.html ファイルをローカル環境にコピーします。このファイルはシンプルな HTML のページで、文字列入力用の <input> フィールドとパラグラフ(段落)要素を含んでいます。また、<script> 要素があり、この中でページ内のHTML 要素の参照を 2 つの変数で保持させています。このページに対して、テキストボックスに数値を入力したら、入力した数値と関連のある異なる数値を下のパラグラフ要素に表示させるようにしていきます。
  2. いくつかの関数を <script> 要素に追加していきましょう。すでに記述されている 2 行の JavaScript のコードの下に、以下の関数定義を追加します。
    function squared(num) {
      return num * num;
    }
    
    function cubed(num) {
      return num * num * num;
    }
    
    function factorial(num) {
      var x = num;
      while (x > 1) {
        num *= x-1;
        x--;
      }
      return num;
    }
    squared() 関数と cubed() 関数は大変わかりやすいでしょう。引数として渡された正方形や立方体の数を返しています。factorial() 関数は引数として渡された数の factorial (階乗)を返しています。
  3. 次に input に入力された数値を出力する処理を追加していきます。イベントハンドラを既存の関数の下に記述しましょう。
    input.onchange = function() {
      var num = input.value;
      if (isNaN(num)) {
        para.textContent = 'You need to enter a number!';
      } else {
        para.textContent = num + ' squared is ' + squared(num) + '. ' +
                           num + ' cubed is ' + cubed(num) + '. ' +
                           num + ' factorial is ' + factorial(num) + '.';
      }
    }

    ここで input での change イベントが発火した時、つまり新しい値が input に入力され、submit された時(たとえば値を入力し、タブを押すなど)に実行される onchange イベントハンドラを作っていきます。この無名関数が実行されると、input に入力された値が num 変数に代入されます。

    次に、条件付きテストを行うようにします。もし入力された値が数値でなければ、パラグラフ要素にエラーメッセージを出力します。テストでは、式 isNaN(num) が true を返すかどうか見るようにします。一般的に値が数値でないかをテストする際には isNaN() 関数を使います。この関数では、渡された値が数値でなければ true を返し、数値であれば false を返します。

    もしテストが false を返した場合、num の値は数値となるので、正方形、立方体、階乗の数が何であるか示すためにパラグラフ要素内に文章を出力します。その出力する文章内で必要とする値を取得するために squared() 関数、cubed() 関数、factorial() 関数を呼ぶようにします。

  4. コードを保存して、それをブラウザで表示してみましょう。

注意: もしサンプルがうまく動作しない場合は、GitHub 上の完成版と比較などしてみてください(実際に動かして確認もできます)。またはお問い合わせください。

この時点で、いくつかの関数を書き出し、それらをライブラリーに追加してもらいたいです。平方根や立方根の数、または半径の長さ num を持った円の円周率はどうでしょうか?

この演習は、return の使い方の学習に加えて、以下の 2 点の他、いくつかの重要なポイントをもたらしてくれました。

  • 関数の中にエラーハンドリングを書く例を見てきました。必要な引数がちゃんと渡されているか、正しいデータ型であるか、そしてもしその引数が必須でなければ、それを許可するために何らかのデフォルト値が渡されているかチェックすることは一般的に良い考え方です。このようにしてプログラムがエラーを投げることを減らせます。
  • 関数のライブラリを作るアイデアについて考えてきました。プログラミングのキャリアを積んでいくと、何度も同じ類のことを繰り返し行うことになるでしょう。そうしたものを頻繁に使う自分独自のユーティリティ関数のライブラリとして保持していくことは良いアイデアです。新しいコードにコピーしたり、必要に応じて HTML ページにそれを適用したりすることができます。

まとめ

以上、関数は楽しく、非常に便利で、構文や機能についてまだまだ話すことはたくさんありますが、学習に最適な記事を読めばかなり理解しやすいものです。

もし何か理解できなかったことがありましたら、何度もこの記事を読み込むか、またはお問い合わせください。

こちらも読んでみる

  • Functions in-depth — より高度な関数に関連した情報を網羅した詳細なガイド。
  • Callback functions in JavaScript — 一般的なJavaScriptのパターンは、ある関数を別の関数に引数として渡すことです。それは受け取った関数の中で呼び出されます。これについては、このコースの範疇を少し超えていますが、すぐにでも勉強する価値はあります。

 

このモジュールの文書

 

ドキュメントのタグと貢献者

このページの貢献者: maechabin
最終更新者: maechabin,