CHAPTER 3 · 9 LESSONS · 114 問
処理をまとめる(関数)
ひとまとまりの処理に名前をつけて、値を渡し、結果を受け取る。同じコードを何度も書かなくてよくなる。
変数が「値に名前をつける」仕組みだったのに対して、関数は「処理に名前をつける」仕組みだよ。この章のテーマはそれだけなのだけれど、影響は大きい。ここから先、書くコードのほとんどは関数の中身になる。
なぜ必要なのか。同じ処理を3か所で書いているとする。仕様が変わったとき、3か所とも直さなければならない。1か所直し忘れれば、そこだけ古い動きのまま残る。こういうバグは見つけにくい。処理を関数にまとめておけば、直す場所は常に1か所で済む。
関数には3つの登場人物がいる。呼び出す側、渡す値、返ってくる値だ。順番に覚えていこう。
まず定義と呼び出し。function greet() { ... } と書いて処理をまとめ、greet() と書いて動かす。定義しただけでは何も起きず、呼び出してはじめて中身が動く。ここは最初によく混乱するところだよ。
次が 引数。関数に外から値を渡す仕組みだ。function greet(name) のように受け取る名前を決めておき、greet("ゆい") のように呼ぶときに実際の値を渡す。これがあるおかげで、同じ関数を違う値で何度でも使い回せる。
そして 戻り値。return で関数から結果を返す。返された値は呼び出した場所で受け取れるので、const total = sum(3, 5) のように書ける。return と console.log の違いは必ず押さえておきたい。console.log は画面に出すだけで、値はどこにも残らない。return は値を呼び出し元に渡すので、その後の計算に使える。「表示する」と「返す」は別のことだよ。
関数の書き方は3通り出てくる。function 宣言、関数式、そしてアロー関数(=>)。どれも同じことができる。今のコードではアロー関数をよく見かけるので、読めるようにはしておこう。
最後に スコープ。関数の中で作った変数は、その関数の中でしか見えない。外からは触れないし、外の同じ名前の変数とぶつかることもない。これは不便な制約ではなく、関数を安心して使い回すための仕組みだ。中で何をしていても外に影響しない、と保証されているから、関数は部品として成立する。
関数をどこで切るか、という悩みもここで出てくる。目安は名前がつけられるかどうかだよ。「この処理は何をしているか」を短い言葉で言えるなら、それは関数にできる。逆に「いろいろやっている」としか言えないなら、まだ切り方が大きすぎる。うまい名前が思いつかないときは、たいてい1つの関数に2つの仕事をさせている。
もうひとつの目安が長さだ。画面に収まらない関数は、たいてい分けたほうがいい。何行までという決まりはないけれど、スクロールしないと全体が見えない関数は、読むときに頭の中に収まらないよ。
関数を覚えると、コードを「小さな部品の組み合わせ」として書けるようになる。長い処理を一息に書くのではなく、意味のある単位に切って名前をつけていく。読みやすさも、直しやすさも、ここから変わってくるよ。
つまずいたときのために、ひとつ手がかりを置いておく。関数が思ったとおりに動かないときは、入口と出口を確かめるといい。関数の先頭で受け取った引数を表示してみる。return の直前で返す値を表示してみる。だいたいこの2か所で、想定と違う値が見つかるよ。
そして実際的な話をすると、ここから先の章はすべて関数の上に建っている。次の章のクラスは「関数をまとめたもの」だし、配列の道具に渡すのも関数だ。関数があいまいなまま進むと、後の章で必ず戻ってくることになる。手が止まったら、遠慮なくこの章に帰ってこよう。
この章のレッスン
関数を作って呼ぶ
結果を返す(戻り値)