Параметры по-умолчанию

Параметры по умолчанию позволяют задавать формальным параметрам функции значения по умолчанию в случае, если функция вызвана без аргументов, или если параметру явным образом передано значение undefined.

Синтаксис

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

Описание

В JavaScript параметры функции, которым при ее вызове не передаются значения, принимают по умолчанию значение undefined. Однако в некоторых случаях может быть полезно задать иное значение по умолчанию. Именно для таких случаев предназначены параметры по умолчанию.

В прошлом для проверки параметров и задания их значений по умолчанию использовался код в теле функции, в котором проверялось, не равны ли значения параметров undefined.

В приведённом ниже примере, в случае если при вызове функции значение для параметра b не передавалось, его значением становилось undefined,  и результатом вычисления a * b в функции multiply получалось значение NaN.

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

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

Чтобы такого не происходило, в теле функции использовался код подобный тому, что находится во второй строчке, где в случае, если функция multiply вызывалась только c одним аргументом, параметру b присваивалось значение 1:

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

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

С появлением в ES2015 параметров по умолчанию стало возможным обходиться без проверки параметров в теле функции. Так, в приведенном выше примере достаточно в заголовке функции указать 1 в качестве значения по умолчанию для параметра b:

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

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

Примеры

Передача значения undefined в сравнении с передачей других "ложных" значений

Значение по умолчанию присваивается формальному параметру только если при вызове функции значение для данного параметра не было передано или было явным образом передано undefined. Если формальному параметру при вызове передано любое значение, отличное от undefined, в том числе одно из "ложных" значений, таких как false, 0, "", '', ``, null, NaN, то в этом случае значение по умолчанию присвоено параметру не будет.  Это иллюстрирует следующий пример:

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

// num не прередано, или передано undefined:
test();          // 'number' (num получил значение 1)
test(undefined); // 'number' (и здесь num получил значение 1)

// num передано значение null или другое "ложное" значение:
test('');        // 'string' (num получил значение '')
test(null);      // 'object' (num получил значение null)

Параметры по умолчанию вычисляются в момент вызова функции

В Javascript параметры по умолчанию вычисляются в момент вызова функции. В отличие от языка Python, при каждом вызове функции создается новое лексическое окружение функции.

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

append(1); // [1]
append(2); // [2], а не [1, 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, "=^_^="]

Инициализация с помощью функций, определяемых в теле функции

Начиная с версии Gecko 33 (Firefox 33 / Thunderbird 33 / SeaMonkey 2.30) функции, определяемые в теле самой функции, не могут быть использованы для инициализации параметров по умолчанию; попытка это сделать приведет к ошибке ReferenceError. Параметры по умолчанию всегда вычисляются до обработки описаний функций, определяемых в теле функции.

// Вызовет ошибку ReferenceError! 
function f(a = go()) {
  function go(){return ":P"}
}
f(); // ReferenceError: go is not defined

Параметры без инициализации, следующие после инициализируемых параметров

До появления версии Gecko 26 (Firefox 26 / Thunderbird 26 / SeaMonkey 2.23 / Firefox OS 1.2), следующий код приводил к SyntaxError. Это было исправлено в баг 777060 и с тех пор работает корректно. Аргументы, передаваемые при вызове функции, становятся значениями формальных параметров независимо от наличия у последних инициализации по умолчанию, а также независимо от присутствия у функции других параметров, находящихся правее в списке параметров и не имеющих инициализации.

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 2015 (6th Edition, ECMA-262)
Определение 'Определение функций' в этой спецификации.
Стандарт Изначальное определение.

Совместимость с браузерами

Update compatibility data on GitHub
КомпьютерыМобильныеServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome для AndroidFirefox для AndroidOpera для AndroidSafari on iOSSamsung 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 ? WebView Android Полная поддержка 49Chrome Android Полная поддержка 49Firefox Android Полная поддержка 41Opera Android ? Safari iOS ? Samsung 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 Полная поддержка Да

Легенда

Полная поддержка  
Полная поддержка
Нет поддержки  
Нет поддержки
Совместимость неизвестна  
Совместимость неизвестна

Смотрите также