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
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
|
---
title: Parámetros predeterminados
slug: Web/JavaScript/Reference/Functions/Default_parameters
tags:
- Característica del lenguaje
- ECMAScript 2015
- Funciones
- JavaScript
translation_of: Web/JavaScript/Reference/Functions/Default_parameters
original_slug: Web/JavaScript/Referencia/Funciones/Parametros_por_defecto
---
<div>{{jsSidebar("Functions", "Funciones")}}</div>
<p><span class="seoSummary"><strong>Parámetros predeterminados de función</strong> permiten que los parámetros con nombre se inicien con valores predeterminados si no se pasa ningún valor o <code>undefined</code>.</span></p>
<div>{{EmbedInteractiveExample("pages/js/functions-default.html")}}</div>
<p class="hidden">La fuente de este ejemplo interactivo se almacena en un repositorio de GitHub. Si deseas contribuir al proyecto de ejemplos interactivos, clona <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> y envíanos una solicitud de extracción.</p>
<h2 id="Sintaxis">Sintaxis</h2>
<pre class="syntaxbox notranslate">function [<var>name</var>]([<var>param1</var>[ = <var>defaultValue1</var> ][, ..., <var>paramN</var>[ = <var>defaultValueN</var> ]]]) {
<var>statements</var>
}
</pre>
<h2 id="Descripción">Descripción</h2>
<p>En JavaScript, los parámetros de función están predeterminados en {{jsxref("undefined")}}. Sin embargo, a menudo es útil establecer un valor predeterminado diferente. Aquí es donde los parámetros predeterminados pueden ayudar.</p>
<p>En el pasado, la estrategia general para establecer valores predeterminados era probar los valores de los parámetros en el cuerpo de la función y asignar un valor si eran <code>undefined</code>.</p>
<p>En el siguiente ejemplo, si no se proporciona ningún valor para <code><var>b</var></code> cuando se llama a <code>multiply</code>, el valor de <code><var>b</var></code> sería <code>undefined</code> al evaluar <code><var>a</var> * <var>b</var></code> y <code>multiply</code> devolvería <code>NaN</code>.</p>
<pre class="brush: js notranslate">function multiply(a, b) {
return a * b
}
multiply(5, 2) // 10
multiply(5) // NaN !
</pre>
<p>Para protegerte contra esto, usarías algo como la segunda línea, donde <code><var>b</var></code> se establece en <code>1</code> si llamas a <code>multiply</code> con un solo argumento:</p>
<pre class="brush: js notranslate">function multiply(a, b) {
b = (typeof b !== 'undefined') ? b : 1
return a * b
}
multiply(5, 2) // 10
multiply(5) // 5
</pre>
<p>Con los parámetros predeterminados en ES2015, las comprobaciones en el cuerpo de la función ya no son necesarias. Ahora, puedes asignar <code>1</code> como valor predeterminado para <code><var>b</var></code> en el encabezado de la función:</p>
<pre class="brush: js notranslate">function multiply(a, b = 1) {
return a * b
}
multiply(5, 2) // 10
multiply(5) // 5
multiply(5, undefined) // 5
</pre>
<h2 id="Ejemplos">Ejemplos</h2>
<h3 id="Pasar_undefined_vs._otros_valores_falsos">Pasar <code>undefined</code> vs. otros valores falsos</h3>
<p>En la segunda llamada de este ejemplo, incluso si el primer argumento se establece explícitamente en <code>undefined</code> (aunque no <code>null</code> u otros valores {{Glossary("falsy", "falsos", "", 1)}} , el valor del argumento <code><var>num</var></code> sigue siendo el predeterminado.</p>
<pre class="brush: js notranslate">function test(num = 1) {
console.log(typeof num)
}
test() // 'number' (num se establece en 1)
test(undefined) // 'number' (num se establece en 1 también)
// prueba con otros valores falsos:
test('') // 'string' (num se establece en '')
test(null) // 'object' (num se establece en null)
</pre>
<h3 id="Evaluado_en_el_momento_de_la_llamada">Evaluado en el momento de la llamada</h3>
<p>El argumento predeterminado se evalúa en el <em>momento de la llamada</em>. Entonces, a diferencia de (por ejemplo) Python, se crea un nuevo objeto cada vez que se llama a la función.</p>
<pre class="brush: js notranslate">function append(value, array = []) {
array.push(value)
return array
}
append(1) // [1]
append(2) // [2], no [1, 2]
</pre>
<p>Esto incluso se aplica a funciones y variables:</p>
<pre class="brush: js notranslate">function callSomething(thing = something()) {
return thing
}
let numberOfTimesCalled = 0
function something() {
numberOfTimesCalled += 1
return numberOfTimesCalled
}
callSomething() // 1
callSomething() // 2
</pre>
<h3 id="Los_parámetros_anteriores_están_disponibles_para_los_parámetros_predeterminados_posteriores">Los parámetros anteriores están disponibles para los parámetros predeterminados posteriores</h3>
<p>Los parámetros definidos anteriormente (a la izquierda) están disponibles para los parámetros predeterminados posteriores:</p>
<pre class="brush: js notranslate">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>Esta funcionalidad se puede aproximar de esta manera, lo que demuestra cuántos casos extremos se manejan:</p>
<pre class="brush: js notranslate">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="Efectos_de_el_ámbito">Efectos de el ámbito</h3>
<p>Si se definen parámetros predeterminados para uno o más parámetros, se crea un <a href="https://tc39.es/ecma262/#sec-functiondeclarationinstantiation">segundo ámbito</a> (registro de entorno), específicamente para los identificadores dentro de la lista de parámetros. Este ámbito es padre del ámbito creado para el cuerpo de la función.</p>
<p>Esto significa que no se puede hacer referencia a las funciones y variables declaradas en el cuerpo de la función desde los iniciadores de parámetros de valor predeterminado; intentar hacerlo arroja un {{jsxref("ReferenceError")}} en tiempo de ejecución.</p>
<p>También significa que las variables declaradas dentro del cuerpo de la función usando <code>var</code> enmascararán los parámetros del mismo nombre, en lugar de que el comportamiento habitual de las declaraciones <code>var</code> duplicadas no tenga ningún efecto.</p>
<p>La siguiente función arrojará un <code>ReferenceError</code> cuando se invoca, porque el valor del parámetro predeterminado no tiene acceso al ámbito secundario del cuerpo de la función:</p>
<pre class="brush: js example-bad notranslate">function f(a = go()) { // Lanza un `ReferenceError` cuando se invoca a `f`.
function go() { return ':P' }
}
</pre>
<p>...y esta función imprimirá <code>undefined</code> porque la variable <code>var a</code> se eleva solo a la parte superior del ámbito creado para el cuerpo de la función (y no hasta el ámbito principal creado para la lista de parámetros):</p>
<pre class="brush: js example-bad notranslate">function f(a, b = () => console.log(a)) {
var a = 1
b() // Imprime `undefined`, porque los valores de los parámetros predeterminados existen en su propio ámbito
}
</pre>
<h3 id="Parámetros_sin_valores_predeterminados_después_de_los_parámetros_predeterminados">Parámetros sin valores predeterminados después de los parámetros predeterminados</h3>
<p>Los parámetros aún se establecen de izquierda a derecha, sobrescribiendo los parámetros predeterminados incluso si hay parámetros posteriores sin valores predeterminados.</p>
<pre class="brush: js notranslate">function f(x = 1, y) {
return [x, y]
}
f() // [1, undefined]
f(2) // [2, undefined]
</pre>
<h3 id="Parámetro_desestructurado_con_asignación_de_valor_predeterminado">Parámetro desestructurado con asignación de valor predeterminado</h3>
<p>Puedes usar la asignación de valor predeterminado con la notación {{jsxref("Operators/Destructuring_assignment", "la desestructuración", "", 1)}}:</p>
<pre class="brush: js notranslate">function f([x, y] = [1, 2], {z: z} = {z: 3}) {
return x + y + z
}
f() // 6</pre>
<h2 id="Especificaciones">Especificaciones</h2>
<table class="standard-table">
<thead>
<tr>
<th scope="col">Especificación</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{SpecName('ESDraft', '#sec-function-definitions', 'Definición de Funciones')}}</td>
</tr>
</tbody>
</table>
<h2 id="Compatibilidad_del_navegador">Compatibilidad del navegador</h2>
<div>
<p>{{Compat("javascript.functions.default_parameters")}}</p>
</div>
<h2 id="Ve_también">Ve también</h2>
<ul>
<li><a class="external" href="http://wiki.ecmascript.org/doku.php?id=harmony:parameter_default_values" rel="external">Propuesta original en ecmascript.org</a></li>
</ul>
|