【JavaScript】引数の記法まとめ

JavaScriptではさまざまな引数の記法があるので備忘録としてまとめておく。

ES2015環境でしか使用できない書き方の場合は見出しに【【ES2015】】と記載する。

# 引数のデフォルト値【ES2015】

引数にデフォルト値を設定する場合は(引数名 = 値)と書くことで設定することができる。

``` sample.js
function argumentSample(num1 = 2, num2 = 5) {
    return num1 + num2;
};

console.log(argumentSample());

```

出力結果
```
7
```


デフォルト値には他の引数や関数の結果などを指定することもできる。

・他の引数を指定するパターン

``` sample.js
function argumentSample(aaa = 2, bbb = aaa) {
    return aaa + bbb;
};

console.log(argumentSample());

```

出力結果

```
4
```




・関数を結果を指定するパターン

``` sample.js
function sampleFunc() {
    return 10;
}


function argumentSample(aaa = 2, bbb = sampleFunc()) {
    return aaa + bbb;
};

console.log(argumentSample());
```

出力結果

```
12
```



## デフォルト値を使用する際の注意点

### 他の引数をデフォルト値として使用する

他の引数をデフォルト値として使用する場合は自身より前に定義されているものでなければならない。
下記のようなコードはエラーが発生する。

``` sample.js
function argumentSample(aaa = bbb, bbb = 5) {
    return aaa + bbb;
};

console.log(argumentSample());
```


出力結果
```
Uncaught ReferenceError: Cannot access 'bbb' before initialization
    at argumentSample (sample.js:1:31)
    at sample.js:5:13
```


## デフォルト値が適用される場合、されない場合

デフォルト値は引数が明示的に渡されなかった場合に適用される。
null,false,0,空文字などでも、明示的に渡された場合は、デフォルト値は適用されない。

``` sample.js
function argumentSample(aaa = "hello", bbb = "world") {
    console.log(aaa);

    console.log(bbb);
};

console.log(argumentSample(null, ""));
```

出力結果

```
null
      ←空文字が出力されている
```


undefinedを引数に渡したときだけは引数は渡されなかったとみなされ、デフォルト値が適用される。

``` sample.js
function argumentSample(aaa = "hello", bbb = "world") {
    console.log(aaa);

    console.log(bbb);
};

console.log(argumentSample(null, undefined));

```

出力結果

```
null
world
```

### デフォルト値を持つ仮引数は引数リストの末尾に書く

これはエラーが発生するものではないが、バグの発生を防ぐための技である。


デフォルト値を持つ仮引数が末尾にないコードがあったとする。

``` samople.js
function argumentSample(num1 = 1, num2) {
    return num1 * num2;
};

console.log(argumentSample(10));
```

argumentSampleに引数が1つしか渡されていない。

この場合、num1にはデフォルト値が適用されて、num2には10が渡されるのかというとそうではない。

出力結果は以下の通りである。

```
NaN
```


実際はnum1に10が渡され、num2には何も渡されない。そのため、undefinedとみなされ、「10×undefined = Nan」となる。

逆にデフォルト値を持つ仮引数を末尾にすることでnum1に10が渡され、上記のバグを回避することができる。

``` sample.js
function argumentSample(num1, num2 = 2) {
    return num1 * num2;
};

console.log(argumentSample(10));
```

出力結果

```
20
```


デフォルト値を持たない引数がundefinedになるだけで、値が渡されなかったといってエラーになるわけではない。

そのため引数を渡すのを必須にしたい場合は下記のように例外をスローする関数をデフォルト値に渡して制御する。

``` sample.js
function required() {
    throw new Error('引数を渡してください');
}

function argumentSample(value = required()) {
    return value;
};

console.log(argumentSample());
```

出力結果
```
Uncaught Error: 引数を渡してください
    at required (sample.js:2:11)
    at argumentSample (sample.js:5:33)
    at sample.js:9:13
```



# 可変長引数【ES2015】

仮引数の前に「...」を書いておくことで、可変長引数になる。
渡された個数の引数を、配列としてまとめて受けとることができる。

``` sample.js
function argumentSample(...values) {
    for(let value of values) {
        console.log(value);
    }
};

argumentSample("aaa", "bbb", "ccc", "ddd", "eee");

```

出力結果
```
aaa
bbb
ccc
ddd
eee
```

この可変長引数はArrayオブジェクトとして扱うことが可能である。


# 名前付き引数

名前付き引数とは下記のように引数に名前を指定することができる記法である。

``` sample.js
argumentSample([{name:"tarou", age:20});

```

名前付き引数には以下のようなメリットがある。

・引数の意味が分かりやすい

・省略可能な引数をわかりやすく表現できる

・引数の順番を変更できる


例えば、先ほどの引数の1つ目省略した場合は下記のようになる

``` sample.js
argumentSample({age:20})
```

引数の順番を入れ替えることも可能。
``` sample.js
argumentSample({age:20, name:"tarou"});
```

引数に名前を付けるのでコードが冗長になるというデメリットはありますが。引数の数が多い場合や、省略可能な引数が多く、省略パターンも様々な場合などには有効である。