JavaScriptのreturnとは何か?「return文」の使い方を徹底研究!
わかるようでわからないreturnの意味
JavaScript だけでなく、プログラミングでは「return文」と呼ばれる記述をすることがあります。
その名の通り、“return”を使ったプログラムのことですが、今一つ何をしているのか初心者にはわかりにくい処理です。
ブラウザのFirefoxを提供しているMozillaの“MDN Web Doc”では、returnを以下のように説明しています。
return 文は、関数の実行を終了して、関数の呼び出し元に返す値を指定します。
return – JavaScript | MDN
ある程度プログラミングに慣れている人であれば、このreturnの説明でも「そうだよね」と思うかもしれません。
しかし、プログラミングを始めたばかりであれば、「関数の実行を終了」や「関数の呼び出し元に返す値」という言葉の意味がわからないということもあるでしょう。
今回はこのreturn文について、初心者の方に向けて解説していきます。
return文の使い道
そもそもこのreturn文はどのような時に使うのでしょうか?
まずはreturn文の使い道を確認していきましょう。
return文は主に以下の2つの目的で使われます[1]When to use return with JavaScript | Go Make Things。
- 呼び出し元に値を返したい
- 関数の実行を終了したい
ここからは、さらに詳しくこれらの用途を見ていきましょう。
return文で関数に値を返す
関数の処理の結果を呼び出すことができる
「関数に値を返す」と言われても、なかなかピンと来ないかもしれません。
説明のために、以下のコードを読んでいきましょう。
- 参考1
<!DOCTYPE html>
<html>
<body>
<p>問題:1+1は?</p>
<p id="demo"></p>
<script>
function myFunction() {
return 1 + 1;
}
document.getElementById("demo").innerHTML = myFunction();
</script>
</body>
</html>
このコードは、「問題:1+1は?」というテキストの下に、その答えをJavaScript を使って表示させるようにしています。
scriptタグの中で、myFunctionという関数が「1+1」をしていることがわかります。
その後に続く、document.getElementById("demo").innerHTML = myFunction();
は「"demo"というidが付いているタグにmyFunctionの内容を表示させる」という命令が書かれています。
その結果、下の画像のように、「問題:1+1は?」というテキストの下にある"demo"のidが付いたpタグにmyFunctionの計算結果である「2」が表示されます。
このように、function myFunction()
で計算した結果を、myFunction()
と記述しただけで使うことができるようになりました。
これがreturn文で関数に値を返すという意味です。
returnを使わないと……
しかし、関数の処理の結果を使えることがそんなにすごいことなのでしょうか?
それくらいであればreturnを使わなくてもできそうな気がします。
ところが、実際にreturn文を使わずに同じことをしようとすると、意外と苦戦することがわかります。
1つ失敗例を見ていきましょう。
- 失敗例1
これは参考1のfunction myFunction()
の中のreturnの記述を消したものです。
プログラミングを始めたばかりの方だと、このコードでも動きそうだと考えます。
しかし、実際には失敗例1の通り、正常に計算結果は表示されず、"undefined"の文字が表示されています。
通常、関数内で行われた処理は、その関数の処理の中でしか記憶されません。
つまり、myFunctionは「1+1」という計算をしたものの、その計算結果の情報をどこにも残さずに処理を終えてしまうのです。
変数を使ってみる
計算結果を保存するのであれば、変数が使えそうです。
しかし、単純に変数を用意しても、次に見る失敗例2のように上手く動作してくれません。
この失敗例2では、"result"という変数を用意し、そこに「1+1」の計算結果を入力しています。
その後、"demo"というidの付いたタグに"result"の内容を表示させようとしていることがわかります。
しかし、この失敗例2のコードは2つの問題点があります。
1つ目は関数の実行がなされていないことです。function myFunction()
という記述は「1+1を変数"result"に代入する」という機能を持っているだけで、それだけでは処理を実行してくれません。myFunction();
という記述があって、はじめてその処理が行われます。
失敗例2のもう1つの問題は、変数"result"がローカル変数になっていることです。
ローカル変数とは、関数の中でだけ使われる変数のことです。
つまり、function myFunction()
の中で"result"というローカル変数に「1+1」の計算結果を入力しても、function myFunction()
の外で変数"result"を呼び出すことはできません。
関数の外でも、関数内で使った変数を使いたい場合は、グローバル変数にする必要があります。
グローバル変数にする方法は簡単で、単に変数の前の"var"を取るだけです。
グローバル変数を使う場合
では、失敗例2はどのようにすれば、参考1と同じ結果を得られるのでしょうか。
以下のコードは失敗例2を修正したものです。
- 参考2
function myFunction()を用意し、その後実行してグローバル変数"result"に「1+1」の計算結果を入力し、その"result"の内容を"demo"のidが付いた箇所へ表示させようとしています。
参考1と参考2を比べると、なぜreturn文を使うのかがわかってくるのではないでしょうか。
両者を比較すると、参考1の方がコードが少なくて済んでいます。
同じ結果であるのであれば、コードのメンテナンスという観点からも、処理の速度という観点からも、コードは少ないに越したことはありません。
return文を使った参考1のコードが優れていることがわかるでしょう。
それだけでなく、参考2はグローバル変数を使っていることも問題です。
例えば、下の失敗例3のように、myFunction();
を実行した後に、result = "いじわる"
という記述をすると、表示される結果が変わってしまっていることがわかります。
- 失敗例3
ここでは詳しくは述べませんが、グローバル変数は関数の内外問わず様々な影響を与えることができますが、逆に影響も受けやすいという性質を持っています。
そのため、グローバル変数が意図しなかった関数に影響を与えたり、逆に与えられたりすることで、バグの温床になることがよくあります。
一見便利なグローバル変数ですが、以上の理由によって、熟練したプログラマーは使用を極力控えるようにしています。
こうしたことから、グローバル変数を使わず、関数の処理の結果を利用しながら、他の関数や変数に影響を与えないようにできることが、return文を使うメリットだといえます。
return文で関数の実行を終了する
ここからはreturn文を使うもう1つの目的である、関数の実行の終了について見ていきます。
この目的については、if-else文と比較していくとわかりやすいでしょう。
例えば下記の参考3のような、ボタンを押すと現在時刻が午後6時(18時)以降なら「こんばんは」、そうでないなら「こんにちは」が表示されるプログラムを書いたとします。
- 参考3
<!DOCTYPE html>
<html>
<body>
<p>あいさつ:</p>
<button onclick="myFunction()">Try it</button>
<p id="demo"></p>
<script>
function myFunction() {
var hour = new Date().getHours();
var greeting;
if (hour >= 18) {
greeting = "こんばんは";
} else {
greeting = "こんにちは";
}
document.getElementById("demo").innerHTML = greeting;
}
</script>
</body>
</html>
この記述は参考4のようにreturn文を使っても同じ結果を得ることができます。
- 参考4
<!DOCTYPE html>
<html>
<body>
<p>Click the button to display a time-based greeting:</p>
<button onclick="myFunction()">Try it</button>
<p id="demo"></p>
<script>
function myFunction() {
var hour = new Date().getHours();
var greeting;
if (hour >= 18) {
greeting = "こんばんは";
return document.getElementById("demo").innerHTML = greeting;
}
greeting = "こんにちは";
document.getElementById("demo").innerHTML = greeting;
}
</script>
</body>
</html>
参考3と参考4を比較すると、"hour"という変数を用意して現在の時刻を代入し、それとは別に"greeting"という変数を用意して、変数"hour"が18以上かどうか、つまり、午後6時以降なのかどうかをif文で判定するところまでは同じです。
参考3は「変数"hour"が18以上であれば『こんばんは』を変数"greeting"に代入する。そうでなければ『こんにちは』を変数"greeting"に代入する」というif-else文で構成しています。
そして、最後に"demo"のidが付いたタグに変数"greeting"の内容を挿入しています。
一方で、参考4は「変数"hour"が18以上であれば『こんばんは』を変数"greeting"に代入する」という部分までは同じですが、return文を使って、"demo"のidが付いたタグに変数"greeting"の内容を挿入しようとしています。
その後、参考4では「『こんにちは』を変数"greeting"に代入する」という記述と、"demo"のidが付いたタグに変数"greeting"の内容を挿入する記述をしています。
参考4はreturn文が使われているため、return document.getElementById("demo").innerHTML = greeting;
が実行された後の内容は実行されません。
つまり、もし変数"hour"が18以上であった場合、return document.getElementById("demo").innerHTML = greeting;
に続けて記述されているgreeting = "こんにちは";
という記述以降の内容は実行されません。
これがreturn文の効果である「関数の実行の終了」です。
このreturn文の効果は、失敗例4のように参考4のコードからreturn文を消してみると、より鮮明になります。
- 失敗例4
return文がない場合は、もし変数"hour"が18以上であり、変数"greeting"に「こんばんは」が代入されても、if文が終わった後に続けてgreeting = "こんにちは";
という記述がなされているため、現在時刻が何時であってもボタンを押した時に「こんにちは」というテキストが表示されてしまいます。
参考4はreturn文で関数の実行を終了したからこそ、if-else文と同じような動きを実現することができたのです。
参考3のように、そこまで複雑でないif-else文であればそこまでreturn文を使う必要はありません。
しかし、if…elseif…elseif…というように、elseifが続いていく複雑なコードを書こうとすると、コードのミスによって意図せぬ結果になる可能性があります。
そのため、複雑なif-else文を書いていくのであれば、return文を使用し、条件に合致する処理を行った後は関数を終了するという対応を行った方が安全である場合が多いです。
以上、return文を使う2つの目的を説明してきましたが、ここまでくれば、冒頭で紹介した「return 文は、関数の実行を終了して、関数の呼び出し元に返す値を指定します。」という説明にも合点がいくのではないでしょうか。
注
↑1 | When to use return with JavaScript | Go Make Things |
---|