はじめてのプログラミングで、JavaScriptを独学中なのですが引数のない関数、また戻り値のない関数というものが腑に落ちません。
関数を自動販売として捉える説明を目にして、そこでは自販に投入する硬貨を引数、下にゴロンを落ちてくる飲み物を戻り値と説明していて、一つの引数があり一つの戻り値がある関数についてよく分かりました。
が、硬貨を投入しない(引数のない)、ないし投入してボタンを押しても何も下に落ちてこない(戻り値のない)関数がよくわからないです。
詳しい方いらしたら教えて頂けたら幸いです、お願いします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答8件
0
普通に関数と聞くと数学の関数を思い浮かべますよね。でも、違うんです。ほとんどのプログラミング言語における関数は**手続き(procedure)であって厳密には数学の関数(function)**では無いんです。ただ、適当な引数を取り、値を返すことができるのであれば、数学の関数のように扱える場合もあるので関数と呼んでいるだけに過ぎないのです。さてそんな関数(実際は手続き)の中で引数や戻り値が無い物はどんな物があるのかを考えていきましょう。
###副作用あり
副作用があるというのは、その関数を評価(実行)すること(関数を評価するとは、関数内にある手続きをそれぞれ順番に再帰的に評価していくことを意味します)で、何かしらの影響、例えばグローバル変数が変わったり、HTMLのテキストが変わったり、コンソールに文字を出力したりすることが起きる場合を言います。また、引数以外の影響、例えば入力や時刻によって戻り値などに変化がある場合も副作用があると言います。
####評価することで関数の外側に何かしらの副作用が生じる関数
JavaScript
1var x = 0; 2function countUp() { 3 x++; 4} 5console.log(x); 6countUp(); 7console.log(x); 8countUp(); 9console.log(x);
上記を実行してみると0 1 2と順番に表示されたと思います(ブラウザでJavaScriptのみを実行するには大変手間がかかります。paiza.ioなどで試して見てください)。countUp();
には引数がありません。これは、countUp
がグローバル変数x
を一つ増分するという副作用を行う手続きだからです。グローバル変数x
以外に対応する気はないので、引数もいりません。副作用の結果はx
を後から参照すればいいので戻り値もいりません。
今回の例はグローバル変数でしたが、特定のメッセージをコンソールに出力する、HTMLのある要素を特定のテキストに変えるなども考えられます。さて、これは良い関数と言えるでしょうか?実はあまり良くない関数です。なぜなら、グローバル変数x
以外に対応することが難しいからです。他もカウントアップしたいと言うとき、そのまま使うことはできません。
####評価したときの状況に応じて値が変わる関数
JavaScript
1var x = 0; 2function getX() { 3 return x; 4} 5console.log(getX()); 6x++; 7console.log(getX()); 8x++; 9console.log(getX());
先ほどとなんとなく似ていますね。このコードの結果も0 1 2と順番に出すようになっています。さて、今度はグローバル変数x
の値を変える所では無く、取得する所を関数にしてみました。getX
はグローバル変数x
の値を取得するだけの手続きです。x
固定なので今回も引数は無しでも良いですね。さてとこれ、getX();
のタイミングによって値が変わっています。そう、これが他に影響が受けて値が変わる(つまり副作用がある)というものです。
同様に、Date.now()
なんかもそうです。これは現在時刻のUNIX時間を返す関数ですが、いつ評価(実行)されたかによって戻り値はバラバラです。現在時刻など、今の状況を取得することが重要な場合もありますので、JavaScriptのような手続き型言語ではよく見られるような書き方です。
####状況に応じて値が変わり、かつ、副作用を生じる関数。
副作用がある関数を二つのパターンで見てきましたが、この二つを組み合わせたような場合もあります。例えば次のようなものです。
JavaScript
1var x = 0; 2function getXwithCountUp() { 3 return x++; 4} 5console.log(getXwithCountUp()); 6console.log(getXwithCountUp()); 7console.log(getXwithCountUp());
実行結果は自分で試して確認してみてください。
###副作用なし
逆に副作用がないことは、引数によって戻り値が必ず一意に決まるような関数です。このとき、グローバル変数など他への影響が一切無いものを言います。このような関数を純粋関数と言います。
####何もしない関数
JavaScript
1funciton noop() {} 2noop();
実行しても何も起きません。全く意味が無い関数です。しかし、意味論的に意味がないだけであり、CPUの命令としては「何もしない」に意味がある場合もあります。CPUレベルでは「何もしない」という処理をするだけで、クロックを消費し、プログラムカウンタが一つ進むという作用があります。ただし、これはCPUレベルでの処理の話で、プログラム言語としてはやはり意味がありません。
おっと、JavaScriptでは厳密にはこのような関数は存在しません。JavaScriptはreturn
文で終わっていない場合は、undefined
を返すと仕様で決められています。つまり、JavaScriptでは戻り値が無い関数は原理的に作れないのです。今までもreturn
文が無い関数をいくつか見てきましたが、実はすべて戻り値としてundefined
を返しています。
####常に同じ値を返す関数
JavaScript
1function tau() { 2 return Math.PI * 2; 3} 4console.log(tau());
円周率πの2倍であるτ(タウ)を標準の数学定数として使うべきだと主張する数学者がいます。そんな人たちのためにtau
関数を作ってみました。実行すると6.283185307179586と表示されます。tau()
で返される値は常に一定です。ですので、引数はいりません。あれ、これっと定数としても良いじゃ無いかと思いました?
JavaScript
1const TAU = Math.PI * 2; 2console.log(TAU);
※ const
はECMAScript 2015から追加された定数を作るキーワードです。古いブラウザでは対応していない場合があります。
同じく実行すると6.283185307179586と表示されます。これは最初の関数とほぼ同じです。ただ、JavaScriptでは、関数は評価される度に毎回計算されていますので、速度面から言うと関数よりも定数の方を使うべきでしょう。
※ 純粋関数型言語の中には(例えばHaskell)、常に同じ値を返す関数と定数を同等に扱う(区別できない)ものもあります。
####引数が空であること自体に意味がある関数
JavaScript
1function sum(...args) { 2 return args.reduce(((acc, v) => acc + v), 0); 3} 4console.log(sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); 5console.log(sum(2, 3, 5, 7)); 6console.log(sum());
※ ...args
および=>
はECMAScript 2015から追加された構文のため、最新のブラウザでないと対応していません。paiza.io等のオンラインコンパイラも対応していません。最新のNode.jsで試してください。
実行すると55 17 0と順番に表示されます。これは引数の総和を求める関数です。引数がある場合が良いですが、引数がない場合はどう考えるべきなのでしょうか?引数を一つの順序づけられた集合と考えると、引数が無いのは空集合です。何かしらの要素がある集合と空集合は異なりますから、空集合も意味があります。ですので、引数が無ければ、引数の合計となる総和は0として、0
を返すようになっています。
###まとめ
自販機の例は関数の動作として具体的なのですが、実は凄くいろいろな要素が詰まっています。引数と戻り値のみならず、自販機の中のジュースの本数やおつりの本数が変わるなど、副作用も考えなくてはなりません。お金足りなければエラーになります(つまりエラー処理)し、戻り値はジュース自体の他にお釣りもあるかも知れません(戻り値を複数にする方法を考慮すべき)。多くのことを一つの事例で表すことは大変難しく、良い例とは言えないと思います。
あと、最初の文で、ほとんどのプログラミング言語と言ったのを覚えてますか?そう、中には数学の関数とほぼ同じ意味で関数を使う言語があります。いわゆる純粋関数型言語と言われるもので、Haskellがその代表格です。もっと数学的な関数として扱いたいというのであれば、一度触ってみることをお勧めします。JavaScriptのようにブラウザ上で動かしたいというのであれば、PureScript(Haskell風のaltJSの一つ)と言う選択肢もありますよ。
投稿2016/07/09 00:19
総合スコア21735
0
「引数がない関数」は引数によって分岐処理せず、ただ一つの処理を実行する関数です。
JavaScript
1' hoge '.trim(); // 前後の空白を取り除く(引数によって取り除く文字が変化しない為、引数を持たない)
引数を持つことが出来るが、引数を省略することでデフォルトの処理が規定されている関数もあります。
JavaScript
1new Date; // Date は引数が省略された時、現在日時を引数として扱う
「戻り値(返り値)を持たない関数」は返り値を返す前に期待する結果が得る処理を実行します。
JavaScript
1alert(1); // アラートダイアログを出すのが目的なので返り値を持たない
Re: hirokihiroki さん
投稿2016/07/08 22:41
編集2016/07/08 22:42総合スコア18162
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
ご質問がたとえ話なので、
関数型言語の概念は持ち出さず、
別のたとえ話をさせていただきます。
たとえますと、ケーブルを他に差し込んで使う家電。
たとえば液晶モニタはPCにケーブルを差し込んで使います。
PCの画像出力信号をモニタに入力して画面を映しているわけですね。
これを関数として見たときに、PC(につないだケーブル)からの
戻り値をモニタの引数に入れてます。
一方ストーブとかは、副作用(放熱)を目的に単体で使います。
つまり、関数に引数や戻り値を設定するかどうかは、
別の関数との間で値を受け渡して使うかどうかです。
このように、引数と戻り値をケーブルの差し込み口と考えれば、
単体か複数か、という違いがイメージしやすいと思います。
投稿2016/07/10 03:12
総合スコア5592
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
jsは関数型言語ではない(関数型のような事も出来ますが)なので、引数と戻り値が全てではありません。
副作用と呼ばれるものがあります。
自動販売機の硬化を引数とし、ジュースを戻り値をする関数を、何も受け取らず、何も返さない関数と考え直してみましょう。
JavaScript
1function ジュースを買う(){ 2 var 投入金額=get投入された金額(); 3 if(投入金額>=価格){ 4 ジュースを出す(); 5 おつりを出す(投入金額-価格); 6 } 7}
このように、引数も戻り値もない関数として定義できます。
しかし、この関数は、引数以外で分岐します。それはget投入された金額()の結果です。
また、戻り値は何も返さなくても、自動販売機に影響を与えます。それは、ジュースを出す()、おつりを出す(投入金額-価格)です。
何故なら自動販売機自信が変化するからです。
このように引数、戻り値は全てではありません。
もし、引数と戻り値が全てではない言語を気持ち悪いと思うのでしたら、関数型言語と呼ばれるものをしてみたらどうでしょう?
あちらは基本的に引数と戻り値が全てで、数学の関数に似ています。
投稿2016/07/08 23:40
総合スコア49
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
自販機の例があまりよくないでしょう。
例えるならば、何かを実行する機械です。
引数なし。戻り値なし。
本当は、これらの関数を作ることが出来ます。
が、javascriptは、作れません。例えば、
javascript
1function kansuu() { 2alert("実行されました"); 3}
という関数を、
javascript
1kansuu()
と呼ぶと、実行されました とアラートが表示されます。
しかし、むりやり戻り値を取得したらどうなるでしょうか。
Javascript
1console.log(kansuu())
undefined と帰ってきたと思います。
実は、戻り値を指定するreturn文がないと、自動的にundefinedが返される仕組みになっています。
だから、そんな腑に落ちない関数ではないと思います。
いろいろ試してみてはいかがでしょうか。
投稿2016/07/11 21:00
総合スコア68
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
幾らでも使う場面があるので、勉強を進めていけば自然と理解できると思います。頑張ってください。
投稿2016/07/11 06:56
退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。