JavaScript 基礎　～関数編～

<h4>・関数の定義方法</h4>
<h5>・関数宣言による定義</h5>
　　<b>関数宣言</b>で関数を定義する場合は、<b>function</b>の後に関数名を記述します。引数は (  )内記述します。

```JavaScript:JavaScript
    function exFunc ( exVal1, exVal2, ...) {
        //処理を書く

        //戻り値がある場合
        return 戻り値
}
```

　<h5>・関数宣言による関数の実行</h5>

```JavaScript:JavaScript
    //戻り値がある場合
    let exValuable(戻り値を格納する変数) = exFunc ( exVal1, exVal2, exVal3...){
        exVal1 + exVal2;
};

    //戻り値がない場合
    exFunc ( exVal1, exVal2, ...);

//関数で定義した引数(仮引数)と、実行文で定義した引数(実引数)が一致しない場合は、実引数の分だけ実行する。

    function add(val1, val2, val3, val4) {
        return val1 + val2 + val3 + val4;
}

    let addResult = add(10, 20);
    console.log(addResult);
    > val3とval4は無視されて、val1とval2を足した30という結果が出る。
```

<h5>・関数式による関数定義</h5>
　　関数式は、関数を変数に代入する方法である。

```JavaScript:JavaScript
    const functionName = function (val1, val2 ...) {
        //処理を書く

        //戻り値がある場合。
        return 戻り値;
}
```

　<h5>・関数式による関数の実行</h5>

```JavaScript:JavaScript
    const add = function(val1, val2) {
        return val1 + val2;
}

let addResult = add ( 30, 10 );

console.log( addResult );
> 40
```

<h4>・関数宣言と関数式の違い</h4>
　<b>・関数名が重複した時</b><br>
　　　<b>関数宣言</b>は、関数名が重複している場合、<b>上書き</b>される。<br>
　　　<b>関数式</b>は、関数名が重複した場合、<b>エラー</b>が発生する。

※<b>ES Modules</b>を有効にすると関数宣言においても重複を許さないようにできる。

　<b>・実行文の記述位置</b>
　　　<b>関数宣言</b>の場合、関数の定義文よりも前に<b>実行文</b>を記述できる。
　　　<b>関数式</b>の場合、関数の定義文よりも前に実行文を記述すると<b>エラー</b>になる。

<h4>・Functionコンストラクタによる関数定義</h4>

```JavaScript:JavaScript
    const add = new Function(val1, val2[引数], "return val1 + val2;[処理を書く]" );
    const addResult = add(10, 20);

    console.log(addResult);
    > 30
```

`eval関数`で直接文字列をコードとして実行することができるが、セキュリティ上、あまり使うべきではない。

例`eval("console.log (1 + 2);"); -> 3`

<h4>・関数を使いこなす</h4>
 <h5>・デフォルト引数</h5>
　関数実行時に値が渡されなかった場合、<b>デフォルト引数</b>という初期値を設定できる。

```JavaScript:JavaScript
    function add ( val1 = 5, val2 = 10 ) {
        return val1 + val2;
    }

console.log( add(1) ) ;
> 11//val1 は設定した１、　val2は引数を渡していないのでデフォルト引数に設定されている10が設定されて計算される。
```

<h5>・オブジェクトに引数をあてる</h5>
　JavaScriptでは、引数の名前を指定して値を渡すことができない。そのため引数が大量になると、文が冗長になったり、引数の順番を間違えると、バグが発生してしまう。<br>
⇒保守などに問題が発生。<br><br>

その問題に対処するために、オブジェクトに引数をあてる、引数をオブジェクトとしてまとめる。

```JavaScript:JavaScript
    function fn ( value1 = "default1", value2 = "default2") {
        console.log(value1, value2);
}

fn (value1 = undefined, value2 = 30);
=>このように、引数の名前を指定して値を渡すことができない。
```

引数をオブジェクトとしてまとめると

```JavaScript:JavaScript
        function functionName( obj ) {
            obj.arg1 ??= "default1";
            obj.arg2 ??= "default2";
            console.log( obj.arg1, obj.arg2 );
    }

    const params = { args: "引数2"; };
    functionName (params);
 > default1   引数2
```

このようにobjというオブジェクトにarg1, arg2という引数をあてる。
`obj.arg1 ??= "default1";`は、Null合体演算子である。
使い方としては、A <b>??</b> B　のように"??"を使って表す。
左のオペラント(A)がnullまたはdefinedの場合、Bの値を返すというものである。

```JavaScript:Null演算子
    let val = null;

    //valはnullなのでdefaultが返される。
    val = val ?? "default";

    //テンプレートリテラル
    console.log (`val [ ${ val }` ] );
    > val [ default ]
    
    let num = 0;
    //numはnullでもdefinedでもないのでそのままnumの値が返される。
    num = num ?? 30;
    console.log(`num [ ${ num } ]`);
    > num [ 0 ]
```

すると今回の場合は、

```JavaScript:JavaScript
        function functionName( obj ) {
            obj.arg1 ??= "default1";
            obj.arg2 ??= "default2";
            console.log( obj.arg1, obj.arg2 );
    }
```

obj.arg1 ??= "default1";  ⇒ obj.arg1がnullまたはdefinedの場合は、default1が、
obj.arg2 ??= "default2";  ⇒ obj.arg2がnullまたはdefinedの場合は、default2が返される。

<h4>・コールバック関数</h4>
　コールバック関数とは、<b>他の関数に引数として渡す関数</b>のことである。

<h5>・関数とオブジェクトの関係</h5>
　結論から述べると、関数とは、<b>実行可能なオブジェクト</b>のことである。関数はオブジェクトの１種であり、オブジェクト{ }と異なるのは、<b>「実行可能である」</b>という点である。そのため、オブジェクト同様に関数にもプロパティ、メソッドの設定、あとからの追加をすることができる。(ドット記法などによって)<br><br>

```JavaScript:コールバック関数の書き方
       function functionName ( callback ) {
            //処理を書く
 
        //コールバック関数の実行
        let result = callback ( [val1, val2(引数がある場合は引数)] );
}
```

```JavaScript:コールバック関数の例
        //コールバック関数を受け取る関数
        function greeting( callback ) {

        //コールバック関数の実行
        const result = callback();
        console.log( `${result}、　ヒルルクさん!` );

        function goodMorning() {
        return "おはようございます!";
}

        function hello() {
        return "こんにちは!";
}

        //コールバック関数を呼ぶときは()を付けない。
        greeting ( goodMorning );
        > おはようございます! 、ヒルルクさん!

        greeting ( hello );
        > こんにちは!、ヒルルクさん!
```

<h4>・アロー関数</h4>
　アロー関数とは、<b>無名関数の省略記法</b>のことである。

```JavaScript:無名関数とアロー関数の比較
    //無名関数
    setTimeout( function() {
                console.log("こんにちは");
    }, 1000);

    //アロー関数
    setTimeout ( () => console.log("こんにちは"), 1000);
```

<h5>・アロー関数の記法</h5>
　<b>①引数がない場合</b>
    
`() => { 関数の本文; };`

<br>※無名関数の場合

`function() { 関数の本文; }`

　<b>②引数が１つの場合</b>

`引数 => { 関数の本文; }`

<br>※無名関数の場合

`function( 引数 ) { 関数の本文; }`

　<b>③引数が複数の場合</b>

`( 引数1, 引数2, ...) => { 関数の本文; }`

<br>※無名関数の場合

`function ( 引数1, 引数2, ...)` { 関数の本文; }

　<b>関数の実行文（本文）が１行の場合</b>

`( 引数1, 引数2, ... ) => 関数の本文;`

```JavaScript:無名関数の場合
    function( 引数1, 引数2, ... ) {
        return 関数の本文;
}
```

　<b>⑤関数の実行文(本文)が複数行の場合</b>

```JavaScript:実行文が複数行
        (引数1, 引数2, ... ) => {
         関数の本文;
         return 戻り値;
}
```

```JavaScript:無名関数の場合
    function(引数1, 引数2, ...) {
        関数の本文;
        return 戻り値;
}
```

　<b>⑥関数の実行文（本文）が1行かつ戻り値がオブジェクトの場合</b>

`(引数1, 引数2, ...) => ( { プロパティ1: 値1, プロパティ2: 値2 } )`

```JavaScript:無名関数の場合
    function( 引数1, 引数2, ...) {
        return { プロパティ1: 値1, プロパティ2: 値2 }
}
```