P64 Chapter8 関数と宣言

【8.2 関数の引数】

  • 8.2.1 呼び出し時の引数が少ないとき

定義した関数の仮引数よりも呼び出し時の引数が少ない場合、余った仮引数にはundefiendという値が代入される。

  • 8.2.2 デフォルト引数[ES2015]

仮引数に対して仮引数 = デフォルト値という構文で、仮引数毎にデフォルト値を指定できる。
デフォルト引数では、引数が渡されなかった場合のみデフォルト値が入る。

  • 8.2.3 呼び出し時の引数が多いとき

関数の仮引数に対して引数の個数が多い場合、あふれた引数は単純に無視される。
但し、後述する可変長引数の記法がある場合は、その限りではない。


【8.3 可変長引数】

  • 8.3.1 Rest parameters[ES2015]

Rest parametersは、仮引数の前に...をつけた仮引数のことで、残余引数とも呼ばれる。
Rest parametersには、関数に渡された値が配列として代入される。

一方、配列を展開して関数の引数に渡すSpread構文というのもある。
Spread構文は、配列の前に...をつけた構文のことで、関数には配列の値を展開したものが引数として渡される。
次のコードでは、arrayの配列を展開してfn関数の引数として渡している。

function fn(x, y, z) {
    console.log(x);
    console.log(y);
    console.log(z);
}
const arrayA = [1, 2, 3];
fn(...arrayA); // fn(arrayA[0], arrayA[1], arrayA[2]);と等価
  • 8.3.2 arguments変数

昔は当文法が使えたが、現代JSではRest parametersを使える環境ではRest parametersを使うべきである。
(理由は本書に記載有)


【8.4 関数の引数と分割代入】

function printUserId({ id }) // {プロパティ変数} という記述が肝
    console.log(id); //42
}

const user = {
    id: 42;
};
printUserId(user);

配列に対しては、以下の様な記述が可能

function print([first, second]) { // 配列の場合は、{}は不要
    console.log(first); // 1
    console.log(second); // 2
}

const array = [1, 2];
print(array);


【8.5 関数はオブジェクト】

  • 8.5.1 関数式
const 変数名 = function() { // 関数式は変数名で参照できるため、関数名は省略できる
    // hoge
}
function 関数名() { // 関数宣言では関数名は省略できない
    // hoge
}

上記の様な名前を持たない関数を匿名関数(無名関数)と呼ぶ。
なお、再帰的に関数を呼びたい場合に匿名関数に名前を付与する場合もある。
但し、名前を付けた場合においても、関数内部から呼び出せても、関数外部から呼び出す事はできない。

- 8.5.2 Arrow Function[ES2015]
(基本文法)

const 変数名 = () => {
    // hoge
    return 関数の返す値; 
};

(Arrow Functionの省略記法)
 ・関数の仮引数が1つのときは()を省略できる
 ・関数の処理が1つの式である場合、ブロックとreturn文を省略できる
  なお、省略した場合は、評価した結果をreturnの返り値として扱う

// 仮引数の定義
const fnA = () => {/* 仮引数がないとき */};
const fnB = (x) => {/* 仮引数が1つのみのとき */};
const fnC = x => {/* 仮引数が1つの時は()を省略可能 */};
const fnD = (x, y) => {/* 仮引数が複数の時 */};
// 次の2つの定義は等価
const mulA = x => {return x * x};
const mulB = x => x * x; // 上記文の略記法

(Arrow Functionの特徴)
 ・名前を付けれない
 ・thisが静的に決定する
 ・functionキーワードに比べて短く書くことが可能である
 ・newできない
 ・arguments変数を参照できない

上記を理解すると、例えば以下の様な記述短縮が生まれる。(※1)

const array = [1, 2, 3];
// 通常記法
const doubleArray = array.map(function(value) {
    return value * 2;
});
console.log(doubleArray); // [2, 4, 6]
//略記法
const doubleArray= array.map(value => value *2);
console.log(doubleArray); // [2, 4, 6]

Arrow Functionで問題ない場合は、Arrow Functionで書き、そうでない場合のみfunctionキーワードを使う事が推奨される。
(thisの問題、関数とスコープ問題が起きにくいコードが書きやすいため)

※1
Java屋にしてみればきもち悪くて仕方ないが、JavaScriptにおいてmapは配列が保持しているお便利関数で、自身の配列の各要素を用いて別の配列を生み出すというメソッドである。
developer.mozilla.org

  • 8.5.3 コールバック関数

引数として渡される関数のことをコールバック関数と呼ぶ。
一方、コールバック関数を引数として扱う関数やメソッドを高階関数と呼ぶ。
例えば、配列のforEachメソッドはコールバック関数を引数として受け取る高階関数である。
forEachメソッドは、配列の各要素に対してコールバック関数を一回呼び出す事ができる。

const arrayA = [1, 2, 3]; //テスト用の配列を宣言しているだけ
const kanB = valueC => console.log(valueC); // コールバック関数 kanB は、引数 valueC をconsole.logに渡して標準出力するだけの関数
arrayA.forEach(kanB); 配列が持っているforEachメソッドを実行する事で、配列内の各値をkanBの引数として実行できる(そのため、kanBは引数は一つのみとなっている)


【8.6 メソッド】
オブジェクトもプロパティとして定義されている関数をメソッドと呼ぶ。
以下の記法で書くことができるが、8.6.1 メソッドの短縮記法にある通り、できればメソッドの短縮記法で書くべきである。

const obj = {
   method1: function() {
        // functionキーワードでのメソッド
    }, //メソッドを複数定義する場合は、メソッド間にカンマが必要
    method2: () => {
        // Arrow Functionでのメソッド
    },
    method3() {
        // 短縮記法
    }
}