関数とは、ある一連の手続き(文の集まり)を1つの処理としてまとめる機能です。関数を利用することで、同じ処理を毎回書くのではなく、一度定義した関数を呼び出すことで同じ処理を実行できます。console.logは「受け取った値をコンソールへ出力する」という処理をまとめた関数です。この章では、関数の定義方法や呼び出し方について見ていきます。関数宣言JavaScriptでは、関数を定義するためにfunctionキーワードを使います。functionからはじまる文は関数宣言と呼び、次のように関数を定義できます。関数は次の4つの要素で構成されています。関数の呼び出し時に渡された値が入る変数。宣言した関数は、関数名()と関数名にカッコをつけることで呼び出せます。引数2)とし、引数が複数ある場合は,(カンマ)で区切ります。関数の中身ではreturn文によって、関数の実行結果として任意の値を返せます。次のコードでは、引数で受け取った値を2倍にして返すmultipleという関数を定義しています。multiple関数にはnumという仮引数が定義されており、10という値を引数として渡して関数を呼び出しています。仮引数のnumには10が代入され、その値を2倍にしたものをreturn文で返しています。20関数でreturn文が実行されると、関数内ではそれ以降の処理は行われません。関数が値を返す必要がない場合は、return文では返り値を省略できます。return文の返り値を省略した場合は、未定義の値であるundefinedを返します。undefined関数が何も値を返す必要がない場合は、return文そのものを省略できます。return文そのものを省略した場合は、undefinedという値を返します。undefined関数の引数JavaScriptでは、関数に定義した仮引数の個数と実際に呼び出したときの引数の個数が違っても、関数を呼び出せます。そのため、引数の個数が合っていないときの挙動を知る必要があります。引数が省略されたときに、デフォルトの値を指定するデフォルト引数という構文についても見ていきます。呼び出し時の引数が少ないとき定義した関数の仮引数よりも呼び出し時の引数が少ない場合、余った仮引数にはundefinedという値が代入されます。次のコードでは、引数として渡した値をそのまま返すecho関数を定義しています。echo関数は仮引数xを定義していますが、引数を渡さずに呼び出すと、仮引数xにはundefinedが入ります。undefined複数の引数を受けつける関数でも同様に、余った仮引数にはundefinedが入ります。次のコードでは、2つの引数を受け取り、それを配列として返すargumentsToArray関数を定義しています。このとき、引数として1つの値しか渡していない場合、残る仮引数にはundefinedが代入されます。デフォルト引数デフォルト引数(デフォルトパラメータ)は、仮引数に対応する引数が渡されていない場合に、デフォルトで代入される値を指定できます。デフォルト値という構文で、仮引数ごとにデフォルト値を指定できます。{}次のコードでは、渡した値をそのまま返すecho関数を定義しています。先ほどのecho関数とは異なり、仮引数xに対してデフォルト値を指定しています。そのため、引数を渡さずにecho関数を呼び出すと、xには"デフォルト値"が代入されます。"デフォルト値"ES2015でデフォルト引数が導入されるまでは、OR演算子(||)を使ったデフォルト値の指定がよく利用されていました。"カスタム:文字列"しかし、OR演算子(||)を使ったデフォルト値の指定にはひとつ問題があります。OR演算子(||)では、左辺のオペランドがfalsyな値の場合に右辺のオペランドを評価します。falsyな値とは、真偽値へと変換するとfalseとなる次のような値のことです。falseundefinednull0NaN""(空文字列)OR演算子(||)を使った場合、次のようにprefixに空文字列を指定した場合にもデフォルト値が入ります。これは書いた人が意図した挙動なのかがとてもわかりにくく、このような挙動はバグにつながることがあります。"カスタム:文字列"デフォルト引数を使って書くことで、このような挙動は起きなくなるため安全です。デフォルト引数では、引数が渡されなかった場合のみデフォルト値が入ります。"カスタム:文字列"呼び出し時の引数が多いとき関数の仮引数に対して引数の個数が多い場合、あふれた引数は単純に無視されます。次コードでは、2つの引数を足し算した値を返すadd関数を定義しています。このadd関数には仮引数が2つしかありません。そのため、3つ以上の引数を渡しても3番目以降の引数は単純に無視されます。関数において引数の数が固定ではなく、任意の個数の引数を受け取りたい場合があります。Math.max(...args)は引数を何個でも受け取り、受け取った引数の中で最大の数値を返す関数です。このような、固定した数ではなく任意の個数の引数を受け取れることを可変長引数と呼びます。parametersか関数の中でのみ参照できるargumentsという特殊な変数を利用します。parametersは、仮引数名の前に...をつけた仮引数のことで、残余引数とも呼ばれます。parametersには、関数に渡された値が配列として代入されます。parametersが定義されています。このfn関数を呼び出したときの引数の値が、argsという変数に配列として代入されます。parametersは、通常の仮引数と組み合わせても定義できます。parametersを末尾の仮引数として定義する必要があります。次のコードでは、1番目の引数はarg1に代入され、残りの引数がrestArgsに配列として代入されます。parametersは、引数をまとめた配列を仮引数に定義する構文でした。一方で、配列を展開して関数の引数に渡すSpread構文もあります。Spread構文は、配列の前に...をつけた構文のことで、関数には配列の値を展開したものが引数として渡されます。次のコードでは、arrayの配列を展開してfn関数の引数として渡しています。array[2]);arguments可変長引数を扱う方法として、argumentsという関数の中でのみ参照できる特殊な変数があります。argumentsは関数に渡された引数の値がすべて入ったArray-likeなオブジェクトです。Array-likeなオブジェクトは、配列のようにインデックスで要素へアクセスできます。Arrayではないため、実際の配列とは異なりArrayのメソッドは利用できないという特殊なオブジェクトです。次のコードでは、fn関数に仮引数が定義されていません。関数の内部ではargumentsという変数で、実際に渡された引数を配列のように参照できます。parametersが利用できる環境では、arguments変数を使うべき理由はありません。arguments変数には次のような問題があります。Functionについては後述)Array-likeオブジェクトであるため、Arrayのメソッドを利用できない関数が可変長引数を受けつけるのかを仮引数だけを見て判断できないarguments変数は仮引数の定義とは関係なく、実際に渡された引数がすべて含まれています。そのため、関数の仮引数の定義部分だけ見ても、実際に関数の要求する引数がわからないという問題を作りやすいです。parametersであれば、仮引数で可変長を受け入れるかが明確になります。parametersでの実装を推奨します。assignment)が利用できます。分割代入はオブジェクトや配列からプロパティを取り出し、変数として定義し直す構文です。次のコードでは、関数の引数としてuserオブジェクトを渡し、idプロパティをコンソールへ出力しています。42};printUserId(user);関数の引数に分割代入を使うことで、このコードは次のように書けます。次のコードのprintUserId関数はオブジェクトを引数として受け取ります。この受け取ったuserオブジェクトのidプロパティを変数idとして定義しています。42};printUserId(user);代入演算子(=)におけるオブジェクトの分割代入では、左辺に定義したい変数を定義し、右辺のオブジェクトから対応するプロパティを代入していました。関数の仮引数が左辺で、関数に渡す引数を右辺と考えるとほぼ同じ構文であることがわかります。42}printUserId(user);関数の引数における分割代入は、オブジェクトだけではなく配列についても利用できます。次のコードでは、引数に渡された配列の1番目の要素がfirstに、2番目の要素がsecondに代入されます。2];print(array);関数はオブジェクトJavaScriptでは、関数は関数オブジェクトとも呼ばれ、オブジェクトの一種です。関数はただのオブジェクトとは異なり、関数名に()をつけることで、関数としてまとめた処理を呼び出すことができます。一方で、()をつけて呼び出されなければ、関数をオブジェクトとして参照できます。関数はほかの値と同じように変数へ代入したり、関数の引数として渡すことが可能です。次のコードでは、定義したfn関数をmyFunc変数へ代入してから、呼び出しています。fn;myFunc();このように関数が値として扱えることを、ファーストクラスファンクション(第一級関数)と呼びます。先ほどのコードでは、関数宣言をしてから変数へ代入していましたが、最初から関数を値として定義できます。Functionを使った方法があります。どちらの方法も、関数を式(代入する値)として扱うため関数式と呼びます。関数式とは、関数を値として変数へ代入している式のことを言います。関数宣言は文でしたが、関数式では関数を値として扱っています。これは、文字列や数値などの変数宣言と同じ定義方法です。関数の返り値;};関数式ではfunctionキーワードの右辺に書く関数名は省略できます。定義した関数式は変数名で参照できるためです。関数宣言ではfunctionキーワードの右辺の関数名は省略できません。{}このように関数式では、名前を持たない関数を変数に代入できます。このような名前を持たない関数を匿名関数(または無名関数)と呼びます。関数式でも関数に名前をつけることができます。この関数の名前は関数の外からは呼ぶことができません。関数の中からは呼ぶことができるため、再帰的に関数を呼び出す際などに利用されます。Functionと呼ばれる書き方があります。名前のとおり矢印のような=>(イコールと大なり記号)を使い、匿名関数を定義する構文です。次のように、functionキーワードを使った関数式とよく似た書き方をします。Functionには書き方にいくつかのパターンがありますが、functionキーワードに比べて短く書けるようになっています。Functionには省略記法があり、次の場合にはさらに短く書けます。Functionについては次のような特徴があります。名前をつけることができない(常に匿名関数)thisが静的に決定できる(詳細は「関数とスコープ」の章で解説します)functionキーワードに比べて短く書くことができるnewできない(コンストラクタ関数ではない)arguments変数を参照できないたとえばfunctionキーワードの関数式では、値を返すコールバック関数を次のように書きます。配列のmapメソッドは、配列の要素を順番にコールバック関数へ渡し、そのコールバック関数が返した値を新しい配列にして返します。Functionでは処理が1つの式だけである場合に、return文を省略し暗黙的にその式の評価結果をreturnの返り値とします。Functionは仮引数が1つである場合は()を省略できます。このような省略はコールバック関数を多用する場合にコードの見通しを良くします。次のコードは、先ほどのfunctionキーワードで書いたコールバック関数と同じ結果になります。Functionはfunctionキーワードの関数式に比べて、できることとできないことがはっきりしています。Functionでは参照できなくなっています。Functionでは、人による解釈や実装の違いが生まれにくくなります。Functionの大きな違いとして、thisという特殊なキーワードに関する挙動の違いがあります。Functionではこのthisの問題の多くを解決できるという利点があります。Functionで書き、そうでない場合はfunctionキーワードを使うことを推奨します。同じ名前の関数宣言は上書きされる関数宣言で定義した関数は、関数の名前でのみ区別されます。そのため、同じ名前の関数を複数回宣言した場合には、後ろで宣言された関数によって上書きされます。次のコードでは、fnという関数名を2つ定義していますが、最後に定義されたfn関数が優先されています。仮引数の定義が異なっていても、関数の名前が同じなら上書きされます。10"この関数定義の上書きはfunctionキーワードでの関数宣言とvarキーワードを使った関数式のみで発生します。letやconstでは同じ変数名の定義はエラーとなるため、このような関数定義の上書きもエラーとなります。このように、同じ関数名で複数の関数を定義することは基本的に意味がないため避けるべきです。引数の違いで関数を呼び分けたい場合は、別々の名前で関数を定義するか関数の内部で引数の値で処理を分岐する必要があります。関数はファーストクラスであるため、その場で作った匿名関数を関数の引数(値)として渡すことができます。引数として渡される関数のことをコールバック関数と呼びます。コールバック関数を引数として使う関数やメソッドのことを高階関数と呼びます。コールバック関数();}たとえば、配列のforEachメソッドはコールバック関数を引数として受け取る高階関数です。forEachメソッドは、配列の各要素に対してコールバック関数を一度ずつ呼び出します。3毎回、関数を定義してその関数をコールバック関数として渡すのは、少し手間がかかります。そこで、関数はファーストクラスであることを利用して、コールバック関数となる匿名関数をその場で定義して渡せます。console.log(value);});コールバック関数は非同期処理においてもよく利用されます。非同期処理におけるコールバック関数の利用方法については「非同期処理」の章で解説します。メソッドオブジェクトのプロパティである関数をメソッドと呼びます。JavaScriptにおいて、関数とメソッドの機能的な違いはありません。呼び方を区別したほうがわかりやすいため、ここではオブジェクトのプロパティである関数をメソッドと呼びます。次のコードでは、objのmethod1プロパティとmethod2プロパティに関数を定義しています。このobj.method1プロパティとobj.method2プロパティがメソッドです。}};次のように空オブジェクトのobjを定義してから、methodプロパティへ関数を代入してもメソッドを定義できます。{};メソッドを呼び出す場合は、関数呼び出しと同様にオブジェクト.メソッド名()と書くことで呼び出せます。先ほどの方法では、プロパティに関数を代入するという書き方になっていました。ES2015からは、メソッドとしてプロパティを定義するための短縮した書き方が追加されています。method"この書き方はオブジェクトのメソッドだけではなく、クラスのメソッドと共通の書き方となっています。メソッドを定義する場合は、できるだけこの短縮記法に統一したほうがよいでしょう。まとめこの章では、次のことについて学びました。基本的な関数の定義や値としての関数について学びました。JavaScriptでは、非同期処理を扱うことが多く、その場合にコールバック関数が使われます。Functionを使うことで、コールバック関数を短く簡潔に書くことができます。JavaScriptでのメソッドは、オブジェクトのプロパティである関数のことです。ES2015からは、メソッドを定義する構文が追加されているため活用していきます。JavaScriptにはオーバーロードと呼ばれる機能はありません。