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
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
|
---
title: Funciones
slug: Web/JavaScript/Referencia/Funciones
tags:
- Funciones
- Guia(2)
- JavaScript
- función
translation_of: Web/JavaScript/Reference/Functions
---
<div>{{jsSidebar("Functions")}}</div>
<p>En términos generales, una función es un "subprograma" que puede ser <em>llamado</em> por código externo (o interno en caso de recursión) a la función. Al igual que el programa en sí mismo, una función se compone de una secuencia de declaraciones, que conforman el llamado <em>cuerpo de la función</em>. Se pueden pasar valores a una función, y la función puede <em>devolver</em> un valor.</p>
<p>En JavaScript, las funciones son objetos de primera clase, es decir, son objetos y se pueden manipular y transmitir al igual que cualquier otro objeto. Concretamente son objetos {{jsxref("Function")}}.</p>
<h2 id="General" name="General">General</h2>
<p>Toda función en JavaScript es un objeto Function. Ver {{jsxref("Function")}} para obtener información sobre las propiedades y métodos de los objetos <code>Function</code>.</p>
<p>Las funciones no son lo mismo que los procedimientos. Una función siempre devuelve un valor, pero un procedimiento, puede o no puede devolver un valor.</p>
<p>Para devolver un valor especifico distinto del predeterminado, una función debe tener una sentencia {{jsxref("Sentencias/return", "return")}}, que especifique el valor a devolver. Una función sin una instrucción return devolverá el valor predeterminado. En el caso de un {{jsxref("Object.prototype.constructor", "constructor")}} llamado con la palabra clave {{jsxref("new")}}, el valor predeterminado es el valor de su parametro. Para el resto de funciones, el valor predeterminado es undefined.</p>
<p>Los parámetros en la llamada a una función son los argumentos de la función. Los argumentos se pasan a las funciones <em>por valor</em>. Si la función cambia el valor de un argumento, este cambio no se refleja globalmente ni en la llamada de la función. Sin embargo, las referencias a objetos también son valores, y son especiales: si la función cambia las propiedades del objeto referenciado, ese cambio es visible fuera de la función, tal y como se muestra en el siguiente ejemplo:</p>
<pre><code class="language-js"><span class="comment token">/* Declarando la función 'myFunc' */</span>
<span class="keyword token">function</span> <span class="function token">myFunc<span class="punctuation token">(elobjeto</span></span><span class="punctuation token">)</span>
<span class="punctuation token">{</span>
elobjeto<span class="punctuation token">.marca</span><span class="operator token">=</span> <span class="string token">"Toyota"</span><span class="brush: js">;</span>
<span class="punctuation token">}</span>
<span class="comment token">/*
* Declarando la variable 'mycar';
* Se crea e inicializa el nuevo objeto;
* para hacer referencia a él mediante 'mycar'
*/</span>
<span class="keyword token">var</span> mycar <span class="operator token">=</span> <span class="punctuation token">{</span>
marca<span class="punctuation token">:</span> <span class="string token">"Honda"</span><span class="punctuation token">,</span>
modelo<span class="punctuation token">:</span> <span class="string token">"Accord"</span><span class="punctuation token">,</span>
año<span class="punctuation token">:</span> <span class="number token">1998</span>
<span class="punctuation token">}</span><span class="punctuation token">;</span>
<span class="comment token">/* Mostrando 'Honda' */</span>
window<span class="punctuation token">.</span><span class="function token">alert<span class="punctuation token">(</span></span>mycar<span class="punctuation token">.marca</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="comment token">/* Paso por referencia del objeto 'mycar' a la función 'myFunc'*/</span>
<span class="function token">myFunc<span class="punctuation token">(</span></span>mycar<span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="comment token">/*
* Muestra 'Toyota' como valor de la propiedad 'marca'
* del objeto, que ha sido cambiado por la función.
*/</span>
window<span class="punctuation token">.</span><span class="function token">alert<span class="punctuation token">(</span></span>mycar<span class="punctuation token">.marca</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>
<p>La palabra clave <a href="/es/docs/Web/JavaScript/Referencia/Operadores/this"><code>this</code></a> no hace referencia a la función que está ejecutandose actualmente, por lo que debes referirte a los objetos Function por nombre, incluso dentro del cuerpo de la función. Como alternativa, puedes utilizar la propiedad <a href="es/Referencia_de_JavaScript_1.5/Funciones/arguments/callee">arguments.callee</a> (que no se recomienda).</p>
<h2 id="Defining_functions" name="Defining_functions">Definiendo funciones</h2>
<p>Hay varias formas de definir funciones:</p>
<h3 id="The_function_declaration_.28function_statement.29" name="The_function_declaration_.28function_statement.29">Declaración de una función (La instrucción <code>function</code>)</h3>
<p>Hay una sintaxis especial para declarar funciones (ver la instrucción {{jsxref("Sentencias/function","function")}} para más detalles):</p>
<pre class="eval">function nombre([<em>param</em>[,<em>param</em>[, ...<em>param</em>]]]) {
instrucciones
}
</pre>
<dl>
<dt><code>nombre</code></dt>
<dd>El nombre de la función.</dd>
</dl>
<dl>
<dt><code>param</code></dt>
<dd>El nombre de un argumento que se pasará a la función. Una función puede tener hasta 255 argumentos.</dd>
</dl>
<dl>
<dt><code>instrucciones</code></dt>
<dd>Las instruciones que forman el cuerpo de la función.</dd>
</dl>
<h3 id="The_function_declaration_.28function_statement.29" name="The_function_declaration_.28function_statement.29">Expresión de una función (El operador <code>function</code>)</h3>
<p>Una expresión function es similar y tiene la misma sintaxis que una declaración de función (ver operador {{jsxref("Operadores/function", "function")}} para más detalles):</p>
<pre class="eval">function [nombre]([<em>param</em>[, <em>param</em>[, ...<em>param</em>]]]) {
instrucciones
}
</pre>
<dl>
<dt><code>nombre</code></dt>
<dd>El nombre de la función, se puede omitir, en ese caso la función se conoce como función anónima.</dd>
</dl>
<dl>
<dt><code>param</code></dt>
<dd>El nombre de los argumentos que se pasarán a la función. Una función puede tener hasta 255 argumentos.</dd>
</dl>
<dl>
<dt><code>instrucciones</code></dt>
<dd>Las instrucciones que forman el cuerpo de la función.</dd>
</dl>
<h3 id="La_expresión_de_función_flecha_>">La expresión de función flecha (=>)</h3>
<div class="note">
<p><strong>Nota:</strong> Las expresiones de función Flecha son una tecnología experimental, parte de la proposición Harmony (EcmaScript 6) y no son ampliamente implementadas por los navegadores.</p>
</div>
<p>Una expresión de función flecha tiene una sintaxis más corta y su léxico se une a este valor (ver {{jsxref("Funciones/Arrow_functions", "arrow functions", "", 1)}} para más detalles):</p>
<pre class="language-html">([param] [, param]) => { instrucciones }
param => expresión
</pre>
<dl>
<dt><code>param</code></dt>
<dd>El nombre de un argumento. Si no hay argumentos se tiene que indicar con <code>()</code>. Para un único argumento no son necesarios los parentesis. (como <code>foo => 1</code>)</dd>
<dt><code>instrucciones o expresión</code></dt>
<dd>Multiples instrucciones deben ser encerradas entre llaves. Una única expresión no necesita llaves. La expresión es, así mismo, el valor de retorno implícito de esa función.</dd>
</dl>
<h3 id="The_Function_constructor" name="The_Function_constructor">El constructor <code>Function</code></h3>
<p>Como todos los demás objetos, los objetos {{jsxref("Function")}} se pueden crear mediante el operador new:</p>
<pre class="language-html">new Function (<em>arg1</em>, <em>arg2</em>, ... <em>argN</em>, <em>functionBody</em>)
</pre>
<dl>
<dt><code>arg1, arg2, ... arg<em>N</em></code></dt>
<dd>Ningún o varios argumentos son pasados para ser utilizados por la función como nombres de argumentos formales. Cada uno debe ser una cadena que se ajuste a las reglas de identificadores válidos en JavaScript, o a una lista de este tipo de cadenas separadas por comas; por ejemplo "x", "theValue", o "a,b".</dd>
</dl>
<dl>
<dt><code>Cuerpo de la función</code></dt>
<dd>Una cadena conteniendo las instrucciones JavaScript que comprenden la definición de la función.</dd>
</dl>
<p>Llamar al contructor Function como una función, sin el operador new, tiene el mismo efecto que llamarlo como un constructor.</p>
<div class="note"><strong>Nota:</strong> Utilizar el constructor Function no se recomienda, ya que necesita el cuerpo de la función como una cadena, lo cual puede ocasionar que no se optimize correctamente por el motor JS, y puede también causar otros problemas.</div>
<h2 id="The_arguments_object" name="The_arguments_object">El objeto <code>arguments</code></h2>
<p>Puedes referirte a los argumentos de una función dentro de la misma, utilizando el objeto arguments. Ver {{jsxref("Functiones/argument", "Function")}}.</p>
<h2 id="Scope_and_the_function_stack" name="Scope_and_the_function_stack">Ámbito de ejecución y pila de funciones</h2>
<p><span class="comment">some section about scope and functions calling other functions</span></p>
<h3 id="Repaso" name="Repaso">Repaso</h3>
<p>Una función puede referirse y llamarse a sí misma. Hay tres maneras en la que una función puede referirse a sí misma.</p>
<ol>
<li>El nombre de la función</li>
<li>{{jsxref("arguments.callee")}}</li>
<li>una función dentro del ambito de ejecución que refiere a la función</li>
</ol>
<p>Por ejemplo, considere la siguiente definición de función:</p>
<pre class="brush: js">var foo = function bar() {
// el cuerpo va aqui
};
</pre>
<p>Dentro del cuerpo de la función, todo lo siguientes son lo mismo:</p>
<ol>
<li><code>bar()</code></li>
<li><code>arguments.callee()</code></li>
<li><code>foo()</code></li>
</ol>
<p>Una función que se llama a sí misma es llamada una <em>función recursiva. </em>En algunas ocaciones, la recursión es análoga a un bucle. Ambos ejecutan el mismo código múltiples veces, y ambas requieren una condición (para evitar un bucle infinito, o en su lugar, recursión infinita en este caso). Por ejemplo, el siguiente bucle:</p>
<pre class="brush: js">var x = 0;
while (x < 10) { // "x < 10" es la condición
// haz algo
x++;
}
</pre>
<p>puede ser convertida en una función recursiva y una llamada a esa función:</p>
<pre class="brush: js">function loop(x) {
if (x >= 10) // "x >= 10" es la condición de salida (equivalente a "!(x < 10)")
return;
// haz algo
loop(x + 1); // la llamada recursiva
}
loop(0);
</pre>
<p>Sin embargo, algunos algoritmos no pueden ser bucles iterativos simples. Por ejemplo, obtener todos los nodos de una estructura de arbol (e.g. el <a href="https://developer.mozilla.org/en-US/docs/DOM">DOM</a>) es realizado de manera más fácil usando recursión:</p>
<pre class="brush: js language-js"><code class="language-js"><span class="keyword token">function</span> <span class="function token">recorrerArbol <span class="punctuation token">(</span></span>nodo<span class="punctuation token">)</span> <span class="punctuation token">{</span>
<span class="keyword token">if</span> <span class="punctuation token">(</span>nodo <span class="operator token">==</span> <span class="keyword token">null</span><span class="punctuation token">)</span><span class="comment token"> //
</span> <span class="keyword token">return</span><span class="punctuation token">;</span>
<span class="comment token"> // haz algo con el nodo
</span> <span class="keyword token">for</span> <span class="punctuation token">(</span><span class="keyword token">var</span> i <span class="operator token">=</span> <span class="number token">0</span><span class="punctuation token">;</span> i <span class="operator token"><</span> nodo<span class="punctuation token">.</span>nodosHijos<span class="punctuation token">.</span>length<span class="punctuation token">;</span> i<span class="operator token">++</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
<span class="function token"><span class="punctuation token"> recorrerArbol(</span></span>nodo<span class="punctuation token">.nodosHijos</span><span class="punctuation token">[</span>i<span class="punctuation token">]</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="punctuation token">}</span>
<span class="punctuation token">}</span></code>
</pre>
<p>En comparación con el bucle de la función <code>loop</code>, cada llamada recursiva hace muchas llamadas recursivas aquí.</p>
<p>Es posible convertir cualquier algoritmo recursivo en uno no recursivo, pero a menudo la lógica es mucho más compleja y hacerlo requiere el uso de una pila. De hecho, la recursión utiliza una pila: la pila de funciones.</p>
<p>El comportamiento similar a la pila se puede ver en el ejemplo siguiente:</p>
<pre class="brush: js language-js"><code class="language-js"><span class="keyword token">function</span> <span class="function token">foo<span class="punctuation token">(</span></span>i<span class="punctuation token">)</span> <span class="punctuation token">{</span>
<span class="keyword token">if</span> <span class="punctuation token">(</span>i <span class="operator token"><</span> <span class="number token">0</span><span class="punctuation token">)</span>
<span class="keyword token">return</span><span class="punctuation token">;</span>
document<span class="punctuation token">.</span><span class="function token">writeln<span class="punctuation token">(</span></span><span class="string token">'inicio:'</span> <span class="operator token">+</span> i<span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="function token">foo<span class="punctuation token">(</span></span>i <span class="operator token">-</span> <span class="number token">1</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
document<span class="punctuation token">.</span><span class="function token">writeln<span class="punctuation token">(</span></span><span class="string token">'fin:'</span> <span class="operator token">+</span> i<span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="punctuation token">}</span>
<span class="function token">foo<span class="punctuation token">(</span></span><span class="number token">3</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>
<p>que produce:</p>
<pre class="language-html">inicio:3
inicio:2
inicio:1
inicio:0
fin:0
fin:1
fin:2
fin:3
</pre>
<h2 id="Nested_functions_and_closures" name="Nested_functions_and_closures">Funciones anidadas y cierres</h2>
<p>Puede anidar una función dentro de una función. La función anidada (inner) es privada a la función que la contiene (outer). También con la forma: aclosure.</p>
<dl>
<dd>Un cierre es una expresión (normalmente una función) que puede tener variables libres junto con un entorno que enlaza esas variables (que "cierra" la expresión).<br>
Dado que una función anidada es un cierre, esto significa que una función anidada puede "heredar" los argumentos y las variables de su función contenedora. En otras palabras, la función interna contiene el ámbito de la función externa. <a class="external" href="http://jibbering.com/faq/faq_notes/closures.html"> </a></dd>
</dl>
<p>Desde que la función anidada es un cierre (closure), esto significa que una función anidada puede "heredar" los argumentos y variables de su función contenedora. En otras palabras, la función interna contiene un scope (alcance) de la función externa.</p>
<p><span class="external">Para resumir: </span></p>
<ul>
<li><span class="external">La función interna se puede acceder sólo a partir de sentencias en la función externa. </span></li>
</ul>
<ul>
<li><span class="external">La función interna forma un cierre: la función interna puede utilizar los argumentos y las variables de la función externa, mientras que la función externa no puede utilizar los argumentos y las variables de la función interna. </span></li>
</ul>
<p><span class="external">El ejemplo siguiente muestra funciones anidadas: </span></p>
<pre class="eval"><span class="brush: js">function addCuadrado(a,b) {
function cuadrado(x) {
return x * x;
}
return cuadrado(a) + cuadrado(b);
}
a = addCuadrado(2,3); // retorna 13
b = addCuadrado(3,4); // retorna 25
c = addCuadrado(4,5); // retorna 41
</span></pre>
<p><span class="external">Dado que la función interna forma un cierre, puede llamar a la función externa y especificar argumentos para la función externa e interna</span></p>
<pre class="eval"><span class="brush: js">function fuerade(x) {
function dentro(y) {
return x + y;
}
return dentro;
}
resultado = fuerade(3)(5); // retorna 8
</span></pre>
<h3 id="Efficiency_considerations" name="Efficiency_considerations"><span class="external">Consideraciones sobre la eficiencia</span></h3>
<p><span class="external">Observe cómo se conserva <code>x</code> cuando se devuelve <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: #eeeeee;">dentro</span></font>. Un cierre conserva los argumentos y las variables en todos los ámbitos que contiene. Puesto que cada llamada proporciona argumentos potencialmente diferentes, debe crearse un cierre para cada llamada a la función externa. En otras palabras, cada llamada a <code>fuerade</code> crea un cierre. Por esta razón, los cierres pueden usar una gran cantidad de memoria. La memoria se puede liberar sólo cuando el <code>dentro</code> devuelto ya no es accesible. En este caso, el cierre del <code>dentro</code> se almacena en <code>resultado</code>. Como el <code>resultado</code> está en el ámbito global, el cierre permanecerá hasta que se descargue el script (en un navegador, esto sucedería cuando la página que contiene el script esté cerrada).</span></p>
<p><span class="external">Debido a esta ineficiencia, evite cierres siempre que sea posible, es decir, evite las funciones de anidamiento siempre que sea posible. Por ejemplo, considere el siguiente ejemplo:</span></p>
<pre class="eval"><span class="brush: js">function assignOnclick(elemento) {
element.onclick = function() {
this.style.backgroundColor = 'blue';
};
}
</span></pre>
<p><span class="external">Esto se puede volver a escribir para evitar el cierre. Sin embargo, la función interna anónima necesitaría ser nombrada y ya no sería privada para <code>assignOnclick</code>: </span></p>
<pre class="eval"><span class="brush: json">function assignOnclick(elemento) {
elemento.onclick = elemento_onclick;
}
function elemento_onclick() {
this.style.backgroundColor = 'blue';
}
</span></pre>
<h4 id="Multiply-nested_functions" name="Multiply-nested_functions">Multiples funciones anidadas</h4>
<p><span class="external">Las funciones pueden ser anidadas contigua de la otra, es decir, una función (A) que contiene una función (B) que contiene una función (C), etc. Ambas funciones B y C forman cierres aquí, por lo que B puede acceder a A y C pueden acceder a B. Además, como C puede acceder a B, que puede acceder a A, C también puede acceder a A. Por lo tanto, los cierres pueden contener múltiples ámbitos; contienen recursivamente el alcance de las funciones que lo contienen. Esto es llamado encadenamiento de objetos(<em>scope chaining</em>). (Por qué se llama "<em>chaining</em>"("encadenamiento") se explicará más adelante.)</span></p>
<p><span class="external">Considere el siguiente ejemplo:</span></p>
<pre class="eval"><span class="brush: js">function A(x) {
function B(y) {
function C(z) {
alert(x + y + z);
}
C(3);
}
B(2);
}
A(1); // alerts 6 (1 + 2 + 3)
</span></pre>
<p><span class="external">En este ejemplo, <code>C</code> accede a las <code>B</code> que hayan en <code>y</code> y <code>A</code> en <code>x</code>. Esto se puede hacer porque: </span></p>
<ol>
<li><span class="external"><code>B</code> forma un cierre que incluye a <code>A</code>, es decir, <code>B</code> puede acceder a los argumentos y variables de <code>A</code>. </span></li>
<li><span class="external"><code>C</code> forma un cierre que incluye a <code>B</code>. </span></li>
<li><span class="external">Como el cierre de <code>B</code> incluye a <code>A</code>, el cierre de <code>C</code> incluye a <code>A</code>, <code>C</code> puede acceder a los argumentos y variables de la Banda <code>A</code>. En otras palabras, codifica los ámbitos de <code>B</code> y A en ese orden. </span></li>
</ol>
<p><span class="external">Lo contrario, sin embargo, no es cierto. <code>A</code> no puede acceder a <code>C</code>, porque <code>A</code> no puede acceder a ningún argumento o variable de <code>B</code>, que <code>C</code> es una variable de. Así, <code>C</code> permanece privado de sólo <code>B</code>. </span></p>
<h3 id="Conflictos_de_nombre" name="Conflictos_de_nombre"><span class="external">Conflictos de nombre </span></h3>
<p><span class="external">Cuando dos argumentos o variables en los ámbitos de un cierre tienen el mismo nombre, existe un conflicto de nombres("<em>name conflict</em>"). Más alcances internos tienen prioridad, por lo que el alcance más interno tiene la más alta precedencia, mientras que el alcance más externo toma el más bajo. Esta es la cadena de alcance. El primero en la cadena es el alcance más interno, y el último es el alcance más exterior. Considera lo siguiente:</span></p>
<pre class="eval"><span class="brush: js">function fuerade() {
var x = 10;
function dentro(x) {
return x;
}
return dentro;
}
resultado = fuerade()(20); // retorna 20 en lugar de 10</span>
</pre>
<p><span class="external">El conflicto de nombres ocurre en la sentencia <code>return x</code> y está entre el parámetro <code>x</code> del <code>dentro</code>y la variable <code>x</code> del <code>fuerade</code>. La cadena de alcance aquí es {<code>dentro</code>, <code>fuerade</code>, global object}. Por lo tanto, la <code>x</code> de <code>inside</code>tiene precedentes sobre la <code>x</code> de <code>fuerade</code>, y 20 (<code>dentro</code>de <code>x</code>) se devuelve en lugar de 10 (<code>fuerade</code> de <code>x</code>).</span></p>
<h2 id="constructor_versus_declaration_versus_expression" name="constructor_versus_declaration_versus_expression"><span class="external">Constructor vs declaración vs expresión</span></h2>
<p><span class="external">Las diferencias entre la <code>Function</code> constructora, la de declaración y la de expresión. </span></p>
<p><span class="external">Compare lo siguiente: </span></p>
<ol>
<li><span class="external">Una función definida con el constructor <code>Function</code> asignado a la variable <code>multiply</code> </span>
<pre><span class="brush: js">var multiply = new Function("x", "y", "return x * y;");
</span></pre>
</li>
<li><span class="external">Una declaración de una función denominada <code>multiply</code> </span>
<pre><span class="brush: js">function multiply(x, y) {
return x * y;
}
</span></pre>
</li>
<li><span class="external">Una expresión de función anónima asignada a la variable <code>multiply</code> </span>
<pre><span class="brush: js">var multiply = function(x, y) {
return x * y;
}
</span></pre>
</li>
<li><span class="external">Una declaración de una función denominada <code>func_name</code> asignada a la variable <code>multiply</code> </span>
<pre><span class="brush: js">var multiply = function func_name(x, y) {
return x * y;
}
</span></pre>
</li>
</ol>
<p><span class="external">Todos hacen aproximadamente la misma cosa, con algunas diferencias sutiles:</span></p>
<ul>
<li><span class="external">Existe una distinción entre el nombre de la función y la variable a la que se asigna la función:</span><span class="external"> </span>
<ul>
<li><span class="external">El nombre de la función no se puede cambiar, mientras que la variable a la que se asigna la función puede ser reasignada.</span></li>
<li><span class="external">El nombre de la función sólo se puede utilizar en el cuerpo de la función. Intentar utilizarlo fuera del cuerpo de la función da como resultado un error (o <code>undefined</code> si el nombre de la función se declaró previamente mediante una instrucción <code>var</code>). Por ejemplo: </span>
<pre><span class="brush: js">var y = function x() {};
alert(x); // arroja un error
</span></pre>
<p><span class="external">El nombre de la función también aparece cuando la función se serializa vía el método de la </span><code>Function</code> 'toString'.</p>
<p>Por otro lado, la variable a la que se asigna la función está limitada sólo por su ámbito, que está garantizado para incluir el ámbito en el que se declara la función.</p>
</li>
<li>Como muestra el ejemplo 4, el nombre de la función puede ser diferente de la variable a la que se asigna la función. No tienen relación entre sí.</li>
</ul>
</li>
<li>Una declaración de función también crea una variable con el mismo nombre que el nombre de la función. Por lo tanto, a diferencia de las definidas por las expresiones de función, las funciones definidas por las declaraciones de función se puede acceder por su nombre en el ámbito que se definieron en:
<pre class="brush: js">function x() {}
alert(x); // salida x serializado en un string
</pre>
<p>El siguiente ejemplo muestra cómo los nombres de las funciones no están relacionados con las variables a las que están asignadas las funciones. Si una "variable de función" se asigna a otro valor, seguirá teniendo el mismo nombre de función:</p>
<pre class="brush: js">function foo() {}
alert(foo); // el string alterado contiene el nombre
// de la función "foo"
var bar = foo;
alert(bar); // el string todavía contiene el nombre
// de la función "foo"
</pre>
</li>
<li>Una función definida por un<code>Function</code> no tiene un nombre de función. Sin embargo, en el <a href="/es/docs/Mozilla/Projetos/SpiderMonkey">SpiderMonkey</a> en el motor de JavaScript, la forma serializada de la función muestra como si tuviera el nombre "anónimo"("anonymous"). Por ejemplo, <code>alert(new Function())</code> salida:
<pre class="brush: js">function anonymous() {
}
</pre>
<p>Dado que la función en realidad no tiene un nombre, <code>anonymous</code> no es una variable que se puede acceder dentro de la función. Por ejemplo, lo siguiente resultaría en un error:</p>
<pre class="brush: js">var foo = new Function("alert(anonymous);");
foo();
</pre>
</li>
<li>A diferencia de las funciones definidas por expresiones de función o constructores <code>Function</code> se puede utilizar una función definida por una declaración de función antes de la propia declaración de la función. Por ejemplo:
<pre class="brush: js">foo(); // alerts FOO!
function foo() {
alert('FOO!');
}
</pre>
</li>
<li>Una función definida por una expresión de función hereda el ámbito actual. Es decir, la función forma un cierre. Por otro lado, una función definida por un constructor de <code>Function</code> no hereda ningún ámbito que no sea el ámbito global (que todas las funciones heredan).</li>
<li>Las funciones definidas por expresiones de función y declaraciones de función son analizadas una sola vez, mientras que las definidas por el constructor de <code>Function</code> no lo son. Es decir, la cadena de cuerpo de función pasada al constructor de <code>Function</code> debe ser analizada cada vez que se evalúa. Aunque una expresión de función crea un cierre cada vez, el cuerpo de la función no es reparsed, por lo que las expresiones de función son aún más rápido que "<code>new Function(...)</code>". Por lo tanto, el constructor de la <code>Function</code> debe evitarse siempre que sea posible.</li>
</ul>
<p>Una declaración de función es muy fácilmente (ya menudo involuntariamente) convertida en una expresión de función. Una declaración de función deja de ser una cuando:</p>
<ul>
<li>Se convierte en parte de una expresión</li>
<li>Ya no es un "elemento fuente" de una función o el propio script. Un "elemento de origen" es una sentencia no anidada en el script o un cuerpo de función:
<pre class="brush: js">var x = 0; // elemento fuente
if (x == 0) { // elemento fuente
x = 10; // no es un elemento fuente
function boo() {} // no es un elemento fuente
}
function foo() { // elemento fuente
var y = 20; // elemento fuente
function bar() {} // elemento fuente
while (y == 10) { // elemento fuente
function blah() {} // no es un elemento fuente
y++; // no es un elemento fuente
}
}
</pre>
</li>
</ul>
<p>Ejemplos:</p>
<ul>
<li>
<pre class="brush: js">// function declaración
function foo() {}
// expresión de una función
(function bar() {})
// expresión de una función
x = function hello() {}
</pre>
</li>
<li>
<pre class="brush: js">if (x) {
// expresión de la función
function world() {}
}
</pre>
</li>
<li>
<pre class="brush: js">// instrucción de la función
function a() {
// instrucción de la función
function b() {}
if (0) {
// expresión de la función
function c() {}
}
}
</pre>
</li>
</ul>
<h3 id="Conditionally_defining_a_function" name="Conditionally_defining_a_function">Definición condicional de una función</h3>
<p>Las funciones se pueden definir de forma condicional utilizando expresiones de función o el constructor <code>Function</code>.</p>
<p>En la siguiente secuencia de comandos, la función <code>zero</code> nunca se define y no se puede invocar, porque '<code>if (0)</code>' se evalúa como false:</p>
<pre class="brush: js">if (0)
function zero() {
document.writeln("Esto es zero.");
}
</pre>
<p>Si se cambia el script para que la condición se convierta en '<code>if (1)</code>', se define la función <code>zero</code>.</p>
<div class="note">
<p>Nota: Aunque esto parece una declaración de función, ésta es en realidad una expresión de función ya que está anidada dentro de otra instrucción. Ver <a href="#constructor_versus_declaration_versus_expression">las diferencias entre las funciones de declaración y de expresión</a>.</p>
</div>
<div class="note">
<p>Nota: Algunos motores JavaScript, sin incluir <a href="/es/docs/Mozilla/Projetos/SpiderMonkey">SpiderMonkey</a>, tratan incorrectamente cualquier expresión de función con un nombre como una declaración de función. Esto llevaría a que se definiera <code>zero</code> incluso con el siempre-falso("<em>always-false</em>") condicional. Una manera más segura de definir funciones condicionalmente es definir la función anónimamente y asignarla a una variable:</p>
</div>
<pre class="brush: js">if (0)
var zero = function() {
document.writeln("Esto es zero.");
}
</pre>
<h2 id="Functions_as_event_handlers" name="Functions_as_event_handlers">Funciones como manejadores de eventos</h2>
<p>En JavaScript, los controladores de eventos <a href="es/DOM">DOM</a> son funciones (en oposición a los objetos que contienen un método <code>handleEvent</code> en otros enlaces de idioma DOM). Las funciones se pasan un objeto de <a href="es/DOM/event">evento</a> como el primer y único parámetro. Como cualquier otro parámetro, si el objeto de evento no necesita ser utilizado, puede omitirse en la lista de parámetros formales.</p>
<p>Los posibles objetivos de eventos en un documento <a href="es/HTML">HTML</a> incluyen: <code>window</code> (<code>Window</code> objects("objeto de ventana"), including frames("marcos")), <code>document</code> (<code>HTMLDocument</code> objects("objetos HTMLDocument")), y elementos (<code>Element</code> objects("objetos Elemento")). En el <a class="external" href="http://www.w3.org/TR/DOM-Level-2-HTML/">HTML DOM</a>, los destinos de evento tienen propiedades de controlador de eventos. Estas propiedades son nombres de eventos en minúsculas con prefijo "on", e.g. <code>onfocus</code>. Los eventos <a class="external" href="http://www.w3.org/TR/DOM-Level-2-Events/">DOM Level 2 Events</a> proporcionan una forma alternativa y más sólida de agregar oyentes de eventos.</p>
<div class="note">
<p>Nota: Los eventos son parte del DOM, no de JavaScript. (JavaScript simplemente proporciona un enlace al DOM.)</p>
</div>
<p>El ejemplo siguiente asigna una función a un manejador de eventos de "foco"("focus") de ventana.</p>
<pre>window.onfocus = function() {
document.body.style.backgroundColor = 'white';
}
</pre>
<p>Si se asigna una función a una variable, puede asignar la variable a un controlador de eventos. El siguiente código asigna una función a la variable <code>setBGColor</code>.</p>
<pre>var setBGColor = new Function("document.body.style.backgroundColor = 'white';");
</pre>
<p>Puede utilizar esta variable para asignar una función a un controlador de eventos de varias maneras. Aquí hay dos formas:</p>
<ol>
<li>Escritura con propiedades de evento DOM HTML<br>
<pre>document.form1.colorButton.onclick = setBGColor;
</pre>
</li>
<li>Atributo de evento HTML<br>
<pre><input name="colorBoton" type="button"
value="Cambia color de fondo"
onclick="setBGColor();"/>
</pre>
<p>Un manejador de eventos establecido de esta manera es en realidad una función, denominada después del atributo, envuelta alrededor del código especificado. Esta es la razón por la que los paréntesis en "<code>setBGColor()</code>" son necesarios aquí (en lugar de sólo "<code>setBGColor</code>").</p>
</li>
</ol>
<p>Es equivalente a:</p>
<pre>document.form1.colorButton.onclick = function onclick(event) {
setBGColor();
}
</pre>
<p>Observe cómo se pasa el objeto de evento a esta función anónima como <code>event</code> de parámetro. Esto permite que el código especificado utilice el objeto Evento("Event object)":</p>
<pre><input ...
onclick="alert(event.target.tagName);"/>
</pre>
<p>Al igual que cualquier otra propiedad que se refiere a una función, el controlador de eventos puede actuar como un método, y <code>this</code> se refiere al elemento que contiene el controlador de eventos. En el ejemplo siguiente, se llama a la función referida por <code>onfocus</code> con <code>this</code> igual a <code>window</code>.</p>
<pre class="eval">window.onfocus();
</pre>
<p>Un error común de principiante de JavaScript es el añadir paréntesis y / o parámetros al final de la variable, es decir, llamar al manejador de eventos cuando lo asigna. La adición de estos paréntesis asignará el <em>valor devuelto al llamar al manejador de eventos</em>, que a menudo es <code>undefined</code> (si la función no devuelve nada), en lugar del controlador de eventos en sí:</p>
<pre class="eval">document.form1.button1.onclick = setBGColor();
</pre>
<p>Para pasar parámetros a un manejador de eventos, el manejador debe ser envuelto en otra función de la siguiente manera:</p>
<pre class="eval">document.form1.button1.onclick = function() {
setBGColor('Algun valor');
};
</pre>
<h3 id="Backward_compatibility" name="Backward_compatibility">Compatibilidad con versiones anteriores</h3>
<h4 id="JavaScript_1.1_and_earlier" name="JavaScript_1.1_and_earlier">JavaScript 1.1 y anteriores</h4>
<p>No puede anidar una sentencia de función en otra instrucción o en sí misma.</p>
<h3 id="Local_variables_within_functions" name="Local_variables_within_functions">Variables locales dentro de las funciones</h3>
<p><a href="es/Referencia_de_JavaScript_1.5/Funciones/arguments">arguments</a>: Objeto similar a una matriz que contiene los argumentos pasados a la función en ejecución.</p>
<p><a href="es/Referencia_de_JavaScript_1.5/Funciones/arguments/callee">arguments.callee</a>: Especifica la función en ejecución.</p>
<p><a href="es/Referencia_de_JavaScript_1.5/Funciones/arguments/caller">arguments.caller</a>: Especifica la función que invocó la función en ejecución.</p>
<p><a href="es/Referencia_de_JavaScript_1.5/Funciones/arguments/length">arguments.length</a>: Especifica el número de argumentos pasados a la función.</p>
<h3 id="Ejemplos" name="Ejemplos">Ejemplos</h3>
<h4 id="1.29_Returning_a_formatted_number" name="1.29_Returning_a_formatted_number">1) Devolver un número con formato</h4>
<p>La siguiente función devuelve una cadena que contiene la representación formateada de un número rellenado con ceros a la izquierda.</p>
<pre class="eval">// Esta función devuelve una cadena rellenada con ceros a la izquierda
function padZeros(num, totalLen) {
var numStr = num.toString(); // Inicializa un valor de retorno como cadena
var numZeros = totalLen - numStr.length; // Calcula el no. de ceros
for (var i = 1; i <= numZeros; i++) {
numStr = "0" + numStr;
}
return numStr;
}
</pre>
<p>Las siguientes sentencias llaman a la función padZeros.</p>
<pre class="eval">var resultado;
resultado = padZeros(42,4); // retorna "0042"
resultado = padZeros(42,2); // retorna "42"
resultado = padZeros(5,4); // retorna "0005"
</pre>
<h4 id="2.29_Determining_whether_a_function_exists" name="2.29_Determining_whether_a_function_exists">2) Determinar si existe una función</h4>
<p>Puede determinar si existe una función utilizando el operador <code>typeof</code>. En el ejemplo siguiente, se realiza una prueba para determinar si el objeto <code>window</code> tiene una propiedad llamada <code>noFunc</code> que es una función. Si es así, se utiliza; de lo contrario, se tomarán otras medidas.</p>
<pre> if ('function' == typeof window.noFunc) {
// utiliza noFunc()
} else {
// hacer algo mas
}
</pre>
<div class="note">
<p>Nota: Tenga en cuenta que en la prueba <code>if</code>, e utiliza una referencia a <code>noFunc</code> aquí no hay paréntesis "()" después del nombre de la función para que la función real no se llame.</p>
</div>
<h3 id="Ver_tambi.C3.A9n" name="Ver_tambi.C3.A9n">Ver también</h3>
<p><a href="es/Referencia_de_JavaScript_1.5/Objetos_globales/Function">Function</a>, <a href="es/Referencia_de_JavaScript_1.5/Sentencias/function">sentencia function</a>, <a href="es/Referencia_de_JavaScript_1.5/Operadores/Operadores_globales/function">operador function</a></p>
<p>{{ languages( { "en": "en/Core_JavaScript_1.5_Reference/Functions", "ru": "ru/\u042f\u0434\u0440\u043e_JavaScript_1.5_\u0421\u043f\u0440\u043e\u0432\u0447\u043d\u0438\u043a/Functions", "fr": "fr/R\u00e9f\u00e9rence_de_JavaScript_1.5_Core/Fonctions", "ja": "ja/Core_JavaScript_1.5_Reference/Functions" } ) }}</p>
|