JavaScriptに再入門しようと思った 関数編

# 目次
[基本構文編](https://qiita.com/A_zara/items/42f895d82550e40c311c)
[オブジェクト編](https://qiita.com/A_zara/items/a2853de304e6334dc342)
[関数編](https://qiita.com/A_zara/private/c4f5c4c74e11d9607488)
# 関数とその定義
　関数とは何たるかの解説に関しては皆さんしていることとし、JavaScriptにおける関数の定義の仕方についてここでは書いていきたいです。
## function命令での定義
```javascript
function fncName (para,...) {
    return para;
}
```
といった形でfunction命令では定義できる。
## functionコンストラクターで定義
Functionオブジェクトをnewすると利用することができる。

```javascript
var fncName = new Function(para, ... ,'return para;');
//省略
var fncname = Function(para, ... ,'return para;');
```
この場合一番最後の引数が関数本体となる。
## 関数リテラルでの定義
通常の場合

```javascript
var fncName = function (para1,para2) {
    return para1 + para2;
}
console.log( fncName(1,2) );
```
アロー関数での定義

```javascript
let fncName = (para1,para2) => {
    return para1 * para2;
}
//または
let fncName = (para1,para2) => para1 * para2;

//引数が1つの場合
let fncName = para1 => para1　*2;

//引数のない場合
let fncName = () => console.log('hey');
```
#関数定義での注意点
##return直後の改行はダメ
returnの後ろで改行をすると当たり前のことながらまともなものが返ってこず、undefinedが返ってくる。
##関数はデータ型の一種
基礎の回で書いたが、関数もデータ型の一種になります。故に代入が可能になります(PHPとかGoから入ってきた僕には少し理解ができなかった)
##function命令は静的構造を宣言
function命令の場合はコンパイルやコード解析のタイミングで関数を定義するのでコード内構造の一部と扱っている。
##関数リテラルとFunctionコンストラクターは実行時評価
function命令に比べこの二つは実行の前に宣言しないと動作しない。つまるところこれらは実行時に評価される。

#変数のスコープ
```javascript
//var宣言あり
var scope = 'グローバル';

function local () {
    var scope = 'ローカル';
    return scope;
}

console.log(local());
console.log(scope);
//var宣言なし
scope = 'グローバル';

function local () {
    scope = 'ローカル';
    return scope;
}

console.log(local());
console.log(scope);
```
　変数にはスコープがあり、functionの外で宣言されるとグローバル、また内部で宣言されるとローカルの扱いを受ける。
　さらにvarの宣言をしない場合、これらはすべてグローバル変数の扱いを受けるため変数の汚染とつながる。そのためvarでの宣言は原則として必要とされている。
 また関数内では外部で定義されたグローバル変数がほかの言語同様にスコープから外れるため関数内で使用する値は引数、または先に定義することが重要である。
## ブロックレベルのスコープ
ES6以前は存在しなかったブロックレベルのスコープがこのES6では利用できるようになった。
それがES6より追加された``` let ```宣言で、このlet宣言はブロック内(ifやwhileなど)で利用するとそのブロック内のみのスコープとなりブロックレベルのスコープが可能となります。

```javascript
if (1) {
    let i = 5;
    console.log(i);
}
console.log(i);//ここでエラー
```
今まではスコープの汚染などを防ぐ目的で利用されてきた即時関数がES6以降はいらなくなり``` { } ```でくくることで配下の変数をlet命令で宣言すれば即時関数と同じ効果を発揮します。

＊switchでのletの使用の際はswitch内での再宣言となるので命令違反になる可能性もある。
# 引数
## ES6以前
###引数の数はチェックしない
　JavaScriptではユーザー定義の関数において引数の数はチェックしない。その理由として仮引数で置かれた引数はそのまま処理されるが、多かった引数は切り捨てが行われる。切り捨てが行われても結果は変わらないで返されます。
###引数の数を図る
```javascript
function fnc (val) {
    var argLen = arguments.length;//argumentsが引数を表す
    console.log(argLen);
}
fnc();

```
## ES6
### 引数のデフォルト値
```javascript
function fnc (val_A = 1, val_B = 1) {
    return val_A * val_B;
}
```
デフォルト値を設定する場合nullやfalseなどを引数に与えたい(0や無しとしての意味)で入れる場合undefinedを入れるとよい。
### 可変長引数
```javascript
function sum (...nums) {
    let result = 0;
    for (let num of nums) {
        if (typeof num !== 'number') {
            throw new Error('指定した値は数値ではありません'+num);
        }
        result += num;
    }
    return result;
}
sum(1, 2, 10);
```
#戻り値
##複数の戻り値を何とか返す方法
```javascript
funcion getMinMax(...nums) {
    return [Math.max(...nums), Math.min(...nums)];//配列で返す
}
```
##高階関数
この関数定義は関数の引数に関数を渡す関数。(関数自体がデータ型なので引数に使える)

```javascript
function arrayWalk (data, f){
    for(var key in data) {
        f(data[key],key)
    }
}
//コールバック関数
function showElement (val,key) {
     console.log(key+':'+val);
}
var ary = [1, 2, 3, 4, 5]
arrayWalk(ary, showElement);
```
この特性を利用し無名関数を利用し使い捨て関数などの実装もできる。

# 参考資料
学習に利用している本
[改訂新版JavaScript本格入門 ～モダンスタイルによる基礎から現場での応用まで](https://www.amazon.co.jp/dp/B01LYO6C1N/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)
[mozilla](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object)