デフォルト引数

関数のデフォルト引数 は、関数に値が渡されない場合や undefined が渡される場合に、デフォルト値で初期化される形式上の引数を指定できます。

構文

function [name]([param1[ = defaultValue1 ][, ..., paramN[ = defaultValueN ]]]) {
   
}

解説

JavaScript では、関数の引数は、指定しなければ undefined になります。しかし、別な既定値を設定すると有用な場合がよくあります。そのような場合に、デフォルト引数が役立ちます。

以前は、既定値を設定するための一般的な方法は、関数の本体で引数の値を検査し、undefined であった場合に値を代入することでした。

次の例では、b の値を指定せずに multiply を呼び出した場合、a * b を評価するときに b の値が undefined となり、multiplyNaN を返します。

function multiply(a, b) {
  return a * b
}

multiply(5, 2)  // 10
multiply(5)     // NaN !

こうなることを防ぐためには、2行目で使われているように、multiply が 1 つだけの引数で呼び出された場合に b1 に設定します。

function multiply(a, b) {
  b = (typeof b !== 'undefined') ?  b : 1
  return a * b
}

multiply(5, 2)  // 10
multiply(5)     // 5

ES2015 のデフォルト引数を用いると、関数本体内のチェックはもはや必要なくなります。関数の先頭で 1b の既定値として設定するだけです。

function multiply(a, b = 1) {
  return a * b 
}

multiply(5, 2)          // 10
multiply(5)             // 5
multiply(5, undefined)  // 5

undefined とその他の falsy な値を渡した場合

この例の 2番目の呼び出しでは、第1引数で明示的に (null やその他の falsy な値ではなく) undefined を設定していても、num 引数の値は既定値のままになります

function test(num = 1) {
  console.log(typeof num)
}

test()           // 'number' (num は 1 に設定)
test(undefined)  // 'number' (こちらも num は 1 に設定)

// 他の falsy な値での検査
test('')         // 'string' (num は '' に設定)
test(null)       // 'object' (num は null に設定)

呼び出し時の評価

デフォルト引数は呼び出し時に評価されるので、Python などと異なり、関数が呼ばれる度に新しいオブジェクトが生成されます。

function append(value, array = []) {
  array.push(value)
  return array
}

append(1)  //[1]
append(2)  //[1, 2] ではなく [2]

これは、関数と変数にも適用されます。

function callSomething(thing = something()) {
  return thing
}

let numberOfTimesCalled = 0
function something() {
  numberOfTimesCalled += 1
  return numberOfTimesCalled
}

callSomething()  // 1
callSomething()  // 2

前の引数を後のデフォルト引数で利用可能

前に (左側で) 定義された引数は、その後のデフォルト引数で利用することができます。

function greet(name, greeting, message = greeting + ' ' + name) {
  return [name, greeting, message]
}

greet('David', 'Hi')                     // ["David", "Hi", "Hi David"]
greet('David', 'Hi', 'Happy Birthday!')  // ["David", "Hi", "Happy Birthday!"]

この機能はこの、いくつもの極端な例を扱うデモに近いかもしれません。

function go() {
  return ':P'
}

function withDefaults(a, b = 5, c = b, d = go(), e = this, 
                      f = arguments, g = this.value) {
  return [a, b, c, d, e, f, g]
}

function withoutDefaults(a, b, c, d, e, f, g) {
  switch (arguments.length) {
    case 0:
      a;
    case 1:
      b = 5;
    case 2:
      c = b;
    case 3:
      d = go();
    case 4:
      e = this;
    case 5:
      f = arguments;
    case 6:
      g = this.value;
    default:
  }
  return [a, b, c, d, e, f, g];
}

withDefaults.call({value: '=^_^='});
// [undefined, 5, 5, ":P", {value:"=^_^="}, arguments, "=^_^="]

withoutDefaults.call({value: '=^_^='});
// [undefined, 5, 5, ":P", {value:"=^_^="}, arguments, "=^_^="]

関数本体の内部で定義された関数

関数の本体の中で宣言された関数は、外側の関数のデフォルト引数の中で参照することができません。これを行おうとすると、ReferenceError が発生します。

デフォルト引数は、常に最初に実行され、関数本体内の関数宣言は、その後に評価されるからです。

// 動作しません。ReferenceError が発生します。
function f(a = go()) {
  function go() { return ':P' }
}

デフォルト引数の後の既定値なしの引数

引数は左から右に設定され、後の引数に既定値がなくてもデフォルト引数を上書きします。

function f(x = 1, y) { 
  return [x, y]  
}

f()   // [1, undefined]
f(2)  // [2, undefined]

既定値のある分割代入の引数

既定値の代入を、分割代入表記で行うことができます。

function f([x, y] = [1, 2], {z: z} = {z: 3}) { 
  return x + y + z
}

f()  // 6

仕様書

仕様書
ECMAScript (ECMA-262)
Function Definitions の定義

ブラウザーの互換性

Update compatibility data on GitHub
デスクトップモバイルサーバー
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewAndroid 版 ChromeAndroid 版 FirefoxAndroid 版 OperaiOSのSafariSamsung InternetNode.js
Default parametersChrome 完全対応 49Edge 完全対応 14Firefox 完全対応 15IE 未対応 なしOpera 完全対応 36Safari 完全対応 10WebView Android 完全対応 49Chrome Android 完全対応 49Firefox Android 完全対応 15Opera Android 完全対応 36Safari iOS 完全対応 10Samsung Internet Android 完全対応 5.0nodejs 完全対応 6.0.0
Destructured parameter with default value assignmentChrome 完全対応 49Edge 完全対応 14Firefox 完全対応 41IE 未対応 なしOpera 完全対応 36Safari 完全対応 10WebView Android 完全対応 49Chrome Android 完全対応 49Firefox Android 完全対応 41Opera Android 完全対応 36Safari iOS 完全対応 10Samsung Internet Android 完全対応 5.0nodejs 完全対応 あり
Parameters without defaults after default parametersChrome 完全対応 49Edge 完全対応 14Firefox 完全対応 26IE 未対応 なしOpera 完全対応 36Safari 完全対応 10WebView Android 完全対応 49Chrome Android 完全対応 49Firefox Android 完全対応 26Opera Android 完全対応 36Safari iOS 完全対応 10Samsung Internet Android 完全対応 5.0nodejs 完全対応 あり

凡例

完全対応  
完全対応
未対応  
未対応

関連情報