aboutsummaryrefslogtreecommitdiff
path: root/files/ru/web/javascript/reference/functions/default_parameters/index.html
blob: 9043c38446a43559a91c20091f4621ffba8a924a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
---
title: Параметры по умолчанию
slug: Web/JavaScript/Reference/Functions/Default_parameters
tags:
  - ECMAScript6
  - JavaScript
  - Функции
  - Экспериментальный
translation_of: Web/JavaScript/Reference/Functions/Default_parameters
---
<div>{{jsSidebar("Functions")}}</div>

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

<p>{{EmbedInteractiveExample("pages/js/functions-default.html")}}</p>

<h2 id="Syntax" name="Syntax">Синтаксис</h2>

<pre class="syntaxbox">function [<em>name</em>]([<em>param1</em>[ = defaultValue1 ][, ..., <em>paramN</em>[ = defaultValueN ]]]) {
   <em>statements</em>
}
</pre>

<h2 id="Example" name="Example">Описание</h2>

<p>В JavaScript параметры функции, которым при ее вызове не передаются значения, принимают по умолчанию значение <code>{{jsxref("undefined")}}</code>. Однако в некоторых случаях может быть полезно задать иное значение по умолчанию. Именно для таких случаев предназначены параметры по умолчанию.</p>

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

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

<pre class="brush: js">function multiply(a, b) {
  return a * b;
}

multiply(5, 2); // 10
multiply(5);    // NaN !</pre>

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

<pre class="brush: js">function multiply(a, b) {
  b = typeof b !== 'undefined' ?  b : 1;
  return a*b;
}

multiply(5, 2); // 10
multiply(5); // 5
</pre>

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

<pre class="brush: js">function multiply(a, b = 1) {
  return a*b;
}

multiply(5, 2); // 10
multiply(5); // 5
multiply(5, undefined); // 5</pre>

<h2 id="Примеры">Примеры</h2>

<h3 id="Передача_значения_undefined_в_сравнении_с_передачей_других_ложных_значений">Передача значения <code>undefined</code> в сравнении с передачей других "ложных" значений</h3>

<p>Значение по умолчанию присваивается формальному параметру только если при вызове функции значение для данного параметра не было передано или было явным образом передано <code>undefined</code>. Если формальному параметру при вызове передано любое значение, отличное от <code>undefined</code>, в том числе одно из <a href="/ru/docs/%D0%A1%D0%BB%D0%BE%D0%B2%D0%B0%D1%80%D1%8C/Falsy">"ложных"</a> значений, таких как <code>false</code>, <code>0</code>, <code>""</code>, <code>''</code>, <code>``</code>, <code>null</code>, <code>NaN</code>, то в этом случае значение по умолчанию присвоено параметру не будет.  Это иллюстрирует следующий пример:</p>

<pre class="brush: js">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)
</pre>

<h3 id="Параметры_по_умолчанию_вычисляются_в_момент_вызова_функции">Параметры по умолчанию вычисляются в момент вызова функции</h3>

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

<pre class="brush: js">function append(value, array = []) {
  array.push(value);
  return array;
}

append(1); // [1]
append(2); // [2], а не [1, 2]

</pre>

<p>Это верно и для функций, и для переменных:</p>

<pre class="brush: js">function callSomething(thing = something()) {
 return thing;
}

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

callSomething(); // 1
callSomething(); // 2
</pre>

<h3 id="Параметры_по_умолчанию_доступны_в_следующих_параметрах_по_умолчанию">Параметры по умолчанию доступны в следующих параметрах по умолчанию</h3>

<p>В параметрах по умолчанию можно использовать значения предыдущих (расположенных левее в списке) параметров:</p>

<pre class="brush: js">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!"]</pre>

<p>Следующий пример пример еще раз иллюстрирует эту возможность, а также позволяет еще раз сравнить два способа достижения одного и того же результата: с использованием инициализации параметров по умолчанию и без ее использования:</p>

<pre class="brush: js">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, "=^_^="]
</pre>

<h3 id="Инициализация_с_помощью_функций_определяемых_в_теле_функции">Инициализация с помощью функций, определяемых в теле функции</h3>

<p>Начиная с версии Gecko 33 {{geckoRelease(33)}} функции, определяемые в теле самой функции, не могут быть использованы для инициализации параметров по умолчанию; попытка это сделать приведет к ошибке {{jsxref("ReferenceError")}}. Параметры по умолчанию всегда вычисляются до обработки описаний функций, определяемых в теле функции.</p>

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

<h3 id="Параметры_без_инициализации_следующие_после_инициализируемых_параметров">Параметры без инициализации, следующие после инициализируемых параметров</h3>

<p>До появления версии Gecko 26 {{geckoRelease(26)}}, следующий код приводил к {{jsxref("SyntaxError")}}. Это было исправлено в {{bug(777060)}} и с тех пор работает корректно. Аргументы, передаваемые при вызове функции, становятся значениями формальных параметров независимо от наличия у последних инициализации по умолчанию, а также независимо от присутствия у функции других параметров, находящихся правее в списке параметров и не имеющих инициализации.</p>

<pre class="brush: js">function f(x=1, y) {
  return [x, y];
}

f(); // [1, undefined];
f(2); // [2, undefined];
</pre>

<h3 id="Инициализация_по_умолчанию_деструктурированных_параметров">Инициализация по умолчанию деструктурированных параметров</h3>

<p>При инициализации параметров по умолчанию можно использовать синтаксическую конструкцию деструктурирующего присваивания:</p>

<pre class="brush: js">function f([x, y] = [1, 2], {z: z} = {z: 3}) {
  return x + y + z;
}

f(); // 6</pre>

<h2 id="Спецификации">Спецификации</h2>

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">Спецификация</th>
   <th scope="col">Статус</th>
   <th scope="col">Комментарий</th>
  </tr>
  <tr>
   <td>{{SpecName('ES6', '#sec-function-definitions', 'Определение функций')}}</td>
   <td>{{Spec2('ES6')}}</td>
   <td>Изначальное определение.</td>
  </tr>
 </tbody>
</table>

<h2 id="Совместимость_с_браузерами">Совместимость с браузерами</h2>

<p>{{Compat("javascript.functions.default_parameters")}}</p>

<h2 id="See_also" name="See_also">Смотрите также</h2>

<ul>
 <li><a href="http://wiki.ecmascript.org/doku.php?id=harmony:parameter_default_values" rel="external">Оригинальное предложение на ecmascript.org</a></li>
</ul>