マッスル・メモリー

筋肉エンジニアのブログ

【js】 引数【ES6】と関数の呼び出し方

ES6で追加された関数の引数の記述と関数の呼び出し方についてまとめていきます!

引数

引数のデフォルト値

ES6で引数のデフォルト値を設定するには、

仮引数 = デフォルト値

とするだけです。

function getTrainingVolume(weight = 80, rep = 10, set = 3) {
  return weight * rep * set;
};

console.log(`ベンチプレスのトレーニングボリュームは${getTrainingVolume()}kgです`);
// ベンチプレスのトレーニングボリュームは2400kgです

また、デフォルト値にはリテラルだけでなく、他の引数や、関数の結果も指定できます。

function multi(a, b = a) {
  return a * b;
};

console.log(multi(10, 5)); // 50
console.log(multi(3)); // 9

ただし、他の引数をデフォルト値とする場合、参照できるのは自身より前に定義されたものだけです。

function multi(a = b, b = 5) {
  return a * b;
};

console.log(multi());
// Cannot access 'b' before initialization

これだと、bがまだ定義されていないのにbをaに代入しようとしているので、エラーになってしまいます。

デフォルト値を使う場合の注意点

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

デフォルト値が適用されるのは、引数が明示的に渡されなかった場合です。

null, false, 0, ''を渡した場合では、デフォルト値は適用されません。

function getTrainingVolume(weight = 80, rep = 10, set = 3) {
  return weight * rep * set;
};

console.log(getTrainingVolume(1, 1, null)); // 0

console.log(getTrainingVolume(1, 1, false)); // 0

console.log(getTrainingVolume(1, 1, 0)); // 0

console.log(getTrainingVolume(1, 1, '')); // 0

console.log(getTrainingVolume(1, 1, undefined)); // 3

80 * 10 * null では結果は0になります。

しかし、undefinedを渡した場合は、デフォルト値が適用されます。

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

デフォルト値が末尾に来ない関数を呼び出す際に引数を1つしか渡さなかったらどうなるでしょうか?

function multi(a = 5, b) {
  return a * b;
};

console.log(multi(10)); // NAN

結果は、10 * undefinedで NAN(not a number)になります。

つまり、引数aに10が渡され、bはデフォルト値を持たないのでundefinedとみなされるのです。

このようのなことが起こらないように、デフォルト値を持つ引数の後に持たない引数を記述しないようにしましょう。

必須の引数を宣言する

jsでは引数にデフォルト値が宣言されているかどうかが、引数の必須 or 任意を表すわけではありません。

デフォルト値を持たない引数に、値を渡さなかったからといって「引数が足りない!」と警告してくれるわけではないのです。

もし引数の必須を表現したいのならば、以下のように記述する必要があります。

function required() {
  throw new Error('引数が足りない!');
}

function square(a = required()) {
  return a ** 2;
};

console.log(square(3)); // 9

console.log(square()); // Uncaught Error: 引数が足りない!

引数が指定されなかった場合にrequired関数が実行され例外がスローされます。

可変長引数の関数を定義する

可変長引数の関数とは、引数の個数があらかじめ決まっていない関数のことです。

可変長引数を使わなくても、呼び出す時の引数に配列を指定する方法を使えば同じ事ができます。

function sum(...numbers) {
  return numbers.reduce((sumNumber, number) => {
    return sumNumber + number;
  }, 0);
};

console.log(sum(1, 2, 3)); // 6
console.log(sum(1, 2, 3, 4, 5, 6)); // 21

...(rest演算子)を使用することで、引数をいくつ渡したとしても対応してくれます。

関数の呼び出し方

関数自身を呼び出す 再起関数

再帰関数とは、ある関数が自分自身を呼び出すこと、またはそのような関数のことです。

function sumNumber(number) {
  if (number != 0) {return number + sumNumber(number-1); }
  return 0;
};

sumNumber(2); // 3
sumNumber(100); // 5050

sumNumberでは、引数に受け取った値から-1ずつしていきその合計を返す関数です。

例えば、5を渡したら、5 + 4 + 3 + 2 + 1 を計算します。

この関数では、内部で自分自身を再帰的にに呼び出しています。

再帰関数で注意すべきは終了点があることです。

今回だと引数が0になると0を返し終了しますが、この処理を書かないと無限ループになってしまいます。

気をつけましょう

関数の引数も関数 高階関数

高階関数とは、関数を引数、戻り値として扱う関数です。

function operateArray(data, f) {
  for (let key in data) {
    f(data[key], key);
  }
}

function showElement(value, key) {
  console.log(`${Number(key) + 1}番目の値は「${value}」です`);
}

let ary = [10, 20, 30, 40, 50];
operateArray(ary, showElement);
// 1番目の値は「10」です
// 2番目の値は「20」です
// 3番目の値は「30」です
// 4番目の値は「40」です
// 5番目の値は「50」です

関数operateArrayは引数にdataと関数fをとり、fにしたがって処理を行う高階関数です。

ここではshowElement関数が引数となっています。

この高階関数operateArray関数で使われているshowElementのような関数をコールバック関数といいます。

高階関数を使うことで、コールバック関数を変えることにより処理のベースは変えずに具体的な処理内容だけ差し替えることができます。

このコールバック関数はその場限りの使い捨ての場合が多いため、匿名関数として記述した方がコードがシンプルになります。

function operateArray(data, f) {
  for (let key in data) {
    f(data[key], key);
  }
}

let ary = [10, 20, 30, 40, 50];
operateArray(
  ary,
  (value, key) => {
    console.log(`${Number(key) + 1}番目の値は「${value}」です`);
  }
);
// 1番目の値は「10」です
// 2番目の値は「20」です
// 3番目の値は「30」です
// 4番目の値は「40」です
// 5番目の値は「50」です

このようにコードが短くなっただけでなく、一度限りしか使用しない関数に名前を付けずに済むので、

名前の重複を防ぐことができます!

まとめ

引数のデフォルト値

function getTrainingVolume(weight = 80, rep = 10, set = 3) {
  return weight * rep * set;
}

console.log(`ベンチプレスのトレーニングボリュームは${getTrainingVolume()}kgです`);
// ベンチプレスのトレーニングボリュームは2400kgです
  • null, false, 0, ''を渡した場合では、デフォルト値は適用されない
  • デフォルト値を持つ引数の後に持たない引数を記述しない

可変長引数の関数の定義

function sum(...numbers) {
  return numbers.reduce((sumNumber, number) => {
    return sumNumber + number;
  }, 0);
}

console.log(sum(1, 2, 3)); // 6
console.log(sum(1, 2, 3, 4, 5, 6)); // 21
  • ...(rest演算子)を使用することで、引数をいくつ渡したとしても対応してくれる

再帰関数

function sumNumber(number) {
  if (number != 0) {return number + sumNumber(number-1); }
  return 0;
};

sumNumber(2); // 3
sumNumber(100); // 5050
  • 再帰関数とは、ある関数が自分自身を呼び出すこと、またはそのような関数のこと
  • 終了点を書かないと無限ループになってしまう

高階関数

function operateArray(data, f) {
  for (let key in data) {
    f(data[key], key);
  }
}

let ary = [10, 20, 30, 40, 50];
operateArray(
  ary,
  (value, key) => {
    console.log(`${Number(key) + 1}番目の値は「${value}」です`);
  }
);
// 1番目の値は「10」です
// 2番目の値は「20」です
// 3番目の値は「30」です
// 4番目の値は「40」です
// 5番目の値は「50」です
  • 高階関数とは、関数を引数、戻り値として扱う関数
  • コードが短くできる
  • 名前の重複を防げる