In 'n' Out

知識を取り込み、そして発信する

関数

関数とは何か?

同じ処理を何度も書くと、修正や管理が大変になります。
JavaScriptでは、こうした処理をまとめる方法があります。
それが関数です。
関数には引数・戻り値といった聞きなじみのないものが登場します。
引数とは関数に受け渡すもの、戻り値は関数で処理した結果として受け取る内容です。
まずは、イメージ図を見ていきましょう。

複合機の電源を入れる
複合機の電源を入れるイメージ

複合機の電源を入れるだけの処理です。
電源を入れるだけなので、引数・戻り値ともにありません。

テスト印刷をする
テスト印刷をするイメージ

テスト印刷を行う処理です。
印刷結果を確認するため、引数はありませんが、印刷結果(成功・失敗など)が戻り値として返されます。

FAXを送る
FAXを送るイメージ

FAXを送信する処理です。
FAXを送るには書類が必要になるため、書類が引数になります。
送信結果を受け取る必要がないため、戻り値はありません。

書類をコピーする
書類をコピーするイメージ

書類をコピーする処理です。
コピー元の書類が必要になるため、書類が引数になります。
コピーされた書類が結果として得られるため、コピーされた書類が戻り値になります。

概念を伝えるため、複合機を関数に見立てて説明しましたが、実際の関数の中身は自分で作る必要があります。
関数は、必要な処理をまとめて記述できる仕組みで、目的に応じて自由に内容を作ることができます。
それでは、関数の書き方について見ていきましょう。

名前付き関数

関数には、自分で定義する自作関数と、JavaScriptにあらかじめ用意されている関数があります。
これまで使ってきたalertも、用意されている関数の一つです。

構文

function 関数名(引数){
    処理;
    return 戻り値;
}

functionは関数を作るための宣言で、変数や配列を宣言するのと同じように使用します。
関数名は任意で決められますが、予約語などは避ける必要があります。
()には引数を書きますが、先ほどのイメージのように必要に応じて記述します。
{}ブロック内には実際に実行したい処理を記述します。
戻り値はreturnの後ろに、戻り値の内容を記述しますが、引数同様必要に応じて記述します。
なお、関数は定義しただけでは動かず、関数名()の形で呼び出して初めて実行されます。
それでは、先ほど説明した4パターンに当てはめながら、コード例と動作例を見ていきましょう。

引数・戻り値なしのコード例

//myFunc1.js
function powerOn() {
    alert('電源をOnにしました');
}
<script src="myFunc1.js"></script>
<script>powerOn();</script>

動作例

※このボタンは動作確認用です

このコードは関数のみを実行しています。
引数・戻り値ともにないため、定義したpowerOn関数を呼び出すだけで、alertが表示されます。

引数なし・戻り値ありのコード例

//myFunc2.js
function testPrint() {
    return 'テスト印刷の結果です';
}
       
alert(testPrint());
<script src="myFunc2.js"></script>

動作例

※このボタンは動作確認用です

このコードは引数はありませんが、戻り値を受け取って関数を実行しています。
実行されるとtestPrint関数の中で、テキストを生成して戻り値としてメインスクリプトで受け取っています。

引数あり・戻り値なしのコード例

//myFunc3.js
const str = '書類の内容';

sendFax(str);

function sendFax(s) {
    alert(s);
}
<script src="myFunc3.js"></script>

動作例

※このボタンは動作確認用です

このコードは引数はありますが、戻り値がない状態で関数を実行しています。
引数strが関数に渡されて実行され、関数内でalertに引数の文字列が表示されます。
ここで重要なポイントはsendFax関数にstrを渡して、関数で受け取る変数は同じ名前である必要はありません。
むしろ引数と関数で受け取る変数は別の名前の方が混乱しません。

引数・戻り値ありのコード例

//myFunc4.js
const str = '書類の内容';

alert(copyDocument(str, 2));

function copyDocument(s, n) {
        const copy = s + 'のコピーです\n' + n + '部コピーしました';
    return copy;
}
<script src="myFunc4.js"></script>

動作例

※このボタンは動作確認用です

このコードは引数・戻り値ともにある状態で関数を実行しています。
引数strと数値が関数に渡されて実行され、関数内でalertに表示するための文字列を作成します。
ここで重要なポイントはcopyDocument関数で受け取る引数は、指定した引数と同じ順番で渡されます。
それぞれs・nに代入され、関数内で処理を行い、関数内で定義したcopy変数の内容をメインスクリプトでalertで表示する流れです。
戻り値は、関数の外で利用するための値になります。
このように引数と戻り値をきちんと理解すれば、関数を使いこなすのは難しくなくなるでしょう。

無名関数

関数は、名前を付けて定義するだけでなく、名前を付けずにそのまま使うこともできます。
このように、関数名を持たない関数を無名関数と呼びます。
無名関数は、処理の内容よりもその場で使うことや他の処理に渡すことを目的として使われることが多く、JavaScriptではよく使われる書き方の一つです。
ここでは、書き方の違いに注目して説明します。

構文

変数 = function (引数){
    処理;
    return 戻り値;
};

無名関数は、関数名の代わりに変数へ代入して使います。
実行するときは変数名に()を付けて呼び出します。
無名関数は、関数をそのまま変数に代入して使う書き方です。
名前付き関数を無名関数に書き換えます。

引数・戻り値なしのコード例

//noNameFunc1.js
const noName1 = function() {
    alert('電源をOnにしました');
};
<script src="noNameFunc1.js"></script>
<script>noName1()</script>

引数なし・戻り値ありのコード例

//noNameFunc2.js
const noName2 = function () {
    return 'テスト印刷の結果です';
};
alert(noName2());
<script src="noNameFunc2.js"></script>
<script>noName2()</script>

引数あり・戻り値なしのコード例

//noNameFunc3.js
const str = '書類の内容';

const noName3 = function (s) {
    alert(s);
};

noName3(str);
<script src="noNameFunc3.js"></script>
<script>noName3()</script>

引数・戻り値ありのコード例

//noNameFunc4.js
const str = '書類の内容';

const noName4 = function (s, n) {
    const copy = s + 'のコピーです\n' + n + '部コピーしました';
    return copy;
};

alert(noName4(str, 2));
<script src="myFunc4.js"></script>

名前付き関数で説明した関数を、全く同じ挙動がする無名関数に書き換えました。
名前付き関数との違いは、変数に関数自体を格納しているところです。
変数名に()を付けるだけで呼び出せるので、シンプルな書き方になります。
ただし、あくまでも変数扱いとなるので、最後の}の後ろにはセミコロンを付ける必要があります。
名前付き関数のsendFaxとcopyDocumentは最後に関数を作っても動きますが、無名関数では格納する変数を宣言しなくては実行できません。
これは変数の初期化が行われる前に変数を使うため、無名関数では順番に注意する必要があります。

アロー関数

アロー関数は、無名関数をさらに短く、シンプルに書ける記法です。
見た目が矢印(=>)のようになることから、この名前が付いています。
基本的な考え方や動きは無名関数と同じですが、コード量を減らせるため、JavaScriptではよく使われています。
ここではまず、無名関数との書き方の違いに注目しながら、アロー関数の基本的な構文を確認していきましょう。

構文

変数 = (引数) => {
    処理;
    return 戻り値;
};

アロー関数は、無名関数をさらに省略しています。
実行するときは変数名に()を付けて呼び出します。
それでは、無名関数をアロー関数に書き換えます。

引数・戻り値なしのコード例

//arrowFunc1.js
const arrow1 = () => {
    alert('電源をOnにしました');
};
<script src="arrowFunc2.js"></script>
<script>arrow1()</script>

引数なし・戻り値ありのコード例

//arrowFunc2.js
const arrow2 =  () => {
    return 'テスト印刷の結果です';
};
alert(arrow2());
<script src="arrowFunc3.js"></script>
<script>arrow2()</script>

引数あり・戻り値なしのコード例

//arrowFunc3.js
const str = '書類の内容';

const arrow3 = (s) => {
    alert(s);
};

arrow3(str);
<script src="arrowFunc4.js"></script>
<script>arrow3()</script>

引数・戻り値ありのコード例

//arrowFunc4.js
const str = '書類の内容';

const arrow4 = (s, n) => {
    const copy = s + 'のコピーです\n' + n + '部コピーしました';
    return copy;
};

alert(arrow4(str, 2));

こちらもアロー関数に書き換えただけで、名前付き関数、無名関数と全く同じ動きをします。
変数に関数自体を格納しているところは同じですが、無名関数との大きな違いはfunctionを入力せず()と=>のみで記述しているところです。
無名関数同様、変数に()を使えるだけで呼び出せ、最後の}の後ろにはセミコロンを付ける必要があります。
順番についても無名関数と同様です。

それでは、配列のメソッドの中で使用したアロー関数について改めて説明します。

前出のコード例

//arraySearch3.js
const prices = [120, 300, 450, 800];

const findValue = prices.find(price => price < 400);
alert(findValue);

const someBool = prices.some(price => price < 400);
alert(someBool);

const everyBool = prices.every(price => price < 400);
alert(everyBool);

こちらもアロー関数なのですが、構文とは違った書き方になっています。
配列のメソッドの内容量が多すぎたため、説明を後述としましたが、実は処理が1行の場合、ブロック{}で囲む必要はない省略形の書き方です。
returnも書かなくとも暗黙的に戻り値を扱えます。
省略しないで書くと以下のようになります。

コード例

//arraySearch3.js
const prices = [120, 300, 450, 800];

const findValue = prices.find((price) => {
    return price < 400;
});
alert(findValue);

const someBool = prices.some((price) => {
    return price < 400;
});
alert(someBool);

const everyBool = prices.every((price) => {
    return price < 400;
});
alert(everyBool);

省略形は短く書けて便利ですが、returnが省略されるため関数が何を返しているのか分かりにくくなり、混乱の元になりやすい書き方です。
そのため、よほどのことがない限り基本形で書くことをおすすめします。

関数の書き方に種類はありますが、どれが正解ということはありません。
すべての関数を名前付き関数だけで書くことも問題ではありませんが、チームワークとなると話は別になるでしょう。
まずは名前付き関数から無名関数、アロー関数への書き換えができるように慣れることが大切です。