forked from BonsaiDen/JavaScript-Garden
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
1881 lines (1414 loc) · 81.1 KB
/
index.html
File metadata and controls
1881 lines (1414 loc) · 81.1 KB
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
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html><html lang="es"><head><title>Jardín de JavaScript</title><meta charset="utf-8"><meta name="description" content="Una guía sobre lo peculiar y defectos de JavaScript."><link rel="stylesheet" href="../style/garden.css" media="all"><link rel="stylesheet" href="../style/print.css" media="print"><!--[if lt IE 9]>
<script src="javascript/html5.js"></script>
<![endif]-->
</head><body><!-- Navigation--><nav id="nav_main"><div><ul><li><a href="/JavaScript-Garden/pl" title="JavaScript Garden - ogród JavaScript po polsku">pl</a></li><li><a href="/JavaScript-Garden/" title="JavaScript Garden in English">en</a></li><li><a href="/JavaScript-Garden/ru" title="JavaScript Гарден по-русски">ru</a></li><li><a href="/JavaScript-Garden/zh" title="JavaScript Garden 中文翻译">zh</a></li><li><a href="/JavaScript-Garden/tr" title="JavaScript Garden Türkçe">tr</a></li><li class="active"><a href="/JavaScript-Garden/es" title="JavaScript Garden es Español">es</a></li><li><a href="/JavaScript-Garden/ja" title="JavaScript Garden in Japanese">ja</a></li><li><a href="/JavaScript-Garden/ko" title="JavaScript Garden">ko</a></li><li><a href="/JavaScript-Garden/fi" title="JavaScript-puutarha suomeksi">fi</a></li></ul><a id="top" href="#intro" title="Back to top">#top</a><a id="hide_menu" class="tablet">Hide Menu</a></div><ul><li class="nav_intro"><h1><a href="#intro">Introducción</a></h1><ul></ul></li><li class="nav_object"><h1><a href="#object">Objetos</a></h1><ul><li><a href="#object.general">Uso de objetos y propiedades</a></li><li><a href="#object.prototype">Prototipo</a></li><li><a href="#object.hasownproperty"><code>hasOwnProperty</code></a></li><li><a href="#object.forinloop">El bucle <code>for in</code></a></li></ul></li><li class="nav_function"><h1><a href="#function">Funciones</a></h1><ul><li><a href="#function.general">La declaración de funciones y expresiones</a></li><li><a href="#function.this">Cómo trabaja <code>this</code></a></li><li><a href="#function.closures">Closures y referencias</a></li><li><a href="#function.arguments">El objeto <code>arguments</code></a></li><li><a href="#function.constructors">Constructores</a></li><li><a href="#function.scopes">Ámbitos y Namespaces</a></li></ul></li><li class="nav_array"><h1><a href="#array">Arrays</a></h1><ul><li><a href="#array.general">Iteración de un Array y sus propiedades</a></li><li><a href="#array.constructor">El constructor <code>Array</code></a></li></ul></li><li class="nav_types"><h1><a href="#types">Types</a></h1><ul><li><a href="#types.equality">Equality and Comparisons</a></li><li><a href="#types.typeof">The <code>typeof</code> Operator</a></li><li><a href="#types.instanceof">The <code>instanceof</code> Operator</a></li><li><a href="#types.casting">Type Casting</a></li></ul></li><li class="nav_core"><h1><a href="#core">Núcleo</a></h1><ul><li><a href="#core.eval">¿Por qué no usar <code>eval</code>?</a></li><li><a href="#core.undefined"><code>undefined</code> y <code>null</code></a></li><li><a href="#core.semicolon">Automatic Semicolon Insertion</a></li></ul></li><li class="nav_other"><h1><a href="#other">Otros</a></h1><ul><li><a href="#other.timeouts"><code>setTimeout</code> and <code>setInterval</code></a></li></ul></li></ul></nav><!-- Mobile navigation--><nav id="nav_mobile"><a id="nav_prev_section" href="#">prev section<span class="nav_section_name">section name</span></a><a id="nav_next_section" href="#">next section<span class="nav_section_name">section name</span></a><a id="show_menu">show menu</a></nav><!-- Sections--><section id="intro"><!-- Introduction--><header id="intro.intro"><h1>Introducción</h1><div><p><strong>El Jardín de JavaScript</strong> es una guía de documentación acerca de las
partes más peculiares de este lenguaje de programación. Brinda consejos para evitar
los errores más comunes y sutiles, así como problemas de rendimiento y de malas
prácticas que los programadores menos experimentados en JavaScript pueden resolver
en sus esfuerzos por profundizar en el lenguaje.</p>
<p>El Jardín de JavaScript <strong>no</strong> prentende enseñar JavaScript.
Se recomienda un conocimiento sobre el lenguaje para entender los temas tratados en
esta guía. Con el fin de aprender los conceptos básicos del lenguaje, por favor
diríjase a la excelente <a href="https://developer.mozilla.org/en/JavaScript/Guide">guía</a> de los desarrolladores de Mozilla.</p>
<h2>Los autores</h2>
<p>Esta guía es el trabajo de dos encantadores usuarios del foro Stack Overflow,
<a href="http://stackoverflow.com/users/170224/ivo-wetzel">Ivo Wetzel</a> (Escrito) y <a href="http://stackoverflow.com/users/313758/yi-jiang">Zhang Yi Jiang</a> (Diseño).</p>
<h2>Colaboradores</h2>
<ul>
<li><a href="https://github.com/caio">Caio Romão</a> (Correciones ortográficas)</li>
<li><a href="https://github.com/blixt">Andreas Blixt</a> (Correciones de idioma)</li>
</ul>
<h2>Hosting</h2>
<p>JavaScript Garden es hospedado en GitHub, además <a href="http://cramerdev.com/">Cramer Development</a> nos apoya
con un sitio espejo en <a href="http://javascriptgarden.info/">JavaScriptGarden.info</a>.</p>
<h2>Licencia</h2>
<p>El Jardín de JavaScript es publicado bajo la <a href="https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE">licencia MIT</a> y es hospedado en
<a href="https://github.com/BonsaiDen/JavaScript-Garden">GitHub</a>. Si encuentra algún error o errata por favor publique <a href="https://github.com/BonsaiDen/JavaScript-Garden/issues">una incidencia</a> o
envie un pull request a nuestro repositorio. También nos puede encontrar en la
<a href="http://chat.stackoverflow.com/rooms/17/javascript">sala de chat de JavaScript</a> en Stack Overflow.</p></div></header><!-- Articles--></section><section id="object"><!-- Introduction--><header id="object.intro"><h1>Objetos</h1></header><!-- Articles--><article id="object.general"><h2>Uso de objetos y propiedades</h2><div><p>Todo en JavaScript actúa como un objeto, con las dos únicas excepciones de
<a href="#core.undefined"><code>null</code></a> y <a href="#core.undefined"><code>undefined</code></a>.</p>
<pre><code>false.toString() // 'false'
[1, 2, 3].toString(); // '1,2,3'
function Foo(){}
Foo.bar = 1;
Foo.bar; // 1
</code></pre>
<p>Un error muy común es el uso de literales númericos como objetos.
Esto se debe a un error en el parser de JavaScript que intenta analizar la
<em>notación de puntos</em> como un literal de punto flotante.</p>
<pre><code>2.toString(); // lanza SyntaxError
</code></pre>
<p>Existe un par de soluciones que pueden utilizarse para hacer que los
literales númericos actúen como objetos.</p>
<pre><code>2..toString(); // el segundo punto es reconocido correctamente
2 .toString(); // observe el espacio a la izquierda del punto
(2).toString(); // el número 2 se evalúa primero
</code></pre>
</div><div><h3>Objetos como un tipo de datos</h3>
<p>Los objetos en JavaScript también pueden ser utilizados como una Tabla Hash o conocido como <a href="http://en.wikipedia.org/wiki/Hashmap"><em>Hashmap</em></a> en inglés, consisten
principalmente en nombres de propiedades asignadoles valores a estos.</p>
<p>El uso de un objeto literal - con notación <code>{}</code> - puede crear un
objeto plano. Este nuevo objeto <a href="#object.prototype">heredado</a> desde <code>Object.prototype</code>
no posee <a href="#object.hasownproperty">propiedades propias</a> definidas.</p>
<pre><code>var foo = {}; // un nuevo objeto vacío
// un nuevo objeto con la propiedad llamada 'test' con el valor 12
var bar = {test: 12};
</code></pre>
</div><div><h3>Acceso a las propiedades</h3>
<p>Se puede acceder a las propiedades de un objeto de dos maneras, ya sea a través de la
notación de punto o desde la notación de corchetes. </p>
<pre><code>var foo = {name: 'Kitten'}
foo.name; // kitten
foo['name']; // kitten
var get = 'name';
foo[get]; // kitten
foo.1234; // SyntaxError
foo['1234']; // ¡funciona!
</code></pre>
<p>Ambas notaciones son idénticas en su funcionamiento, la única diferencia es la
notación de corchetes permite el ajuste dinámico de las propiedades, así como
el uso de propiedades que de otro modo daría lugar a error de sintaxis.</p>
</div><div><h3>Eliminando propiedades</h3>
<p>La única manera de eliminar una propiedad desde un objeto es usando el
operador <code>delete</code>; Se establece la propiedad a <code>undefined</code> o <code>null</code> sólo al
<em>valor</em> asociado de la propiedad, pero no ha un <em>key</em> (valor clave).</p>
<pre><code>var obj = {
bar: 1,
foo: 2,
baz: 3
};
obj.bar = undefined;
obj.foo = null;
delete obj.baz;
for(var i in obj) {
if (obj.hasOwnProperty(i)) {
console.log(i, '' + obj[i]);
}
}
</code></pre>
<p>Los resultados de la salida son <code>bar undefined</code> y <code>foo null</code> - sólo <code>baz</code> ha
sido removido y por lo tanto no aparece en la salida.</p>
</div><div><h3>Notación de Keys</h3>
<pre><code>var test = {
'case': 'Soy una palabra clave y debo ser anotado como string',
delete: 'Soy una palabra clave también' // lanza SyntaxError
};
</code></pre>
<p>Las propiedades de los objetos puede ser simbolizados como caracteres planos y como strings. Debido
a otro mal diseño del parser de JavaScript, lo anterior es una excepción
de <code>SyntaxError</code> antes de ECMAScript 5.</p>
<p>Este error se debe al <code>eliminar</code> una <em>keyword</em>; por lo tanto, debe ser
anotado como un <em>string literal</em> para asegurarse que será interpretado correctamente
por diversos motorores de JavaScript.</p></div></article><article id="object.prototype"><h2>Prototipo</h2><div><p>JavaScript no posee en sus características un sistema clásico de herencia, sino que
utiliza un <em>prototipo</em> para esto. </p>
<p>Si bien a menudo se considera uno de los puntos débiles de JavaScript, el
modelo de herecia prototipado es de hecho más poderoso que el modelo clásico.
Por ejemplo, es bastante trivial construir un modelo clásico en la parte superior del mismo,
mientras esto es una tarea mucho más difícil.</p>
<p>Debido al hecho que JavaScript es básicamente el único lenguaje que utiliza
apliamente la herencia prototipada, se necesita algo de tiempo para adaptarse a
las diferencias entre los dos modelos.</p>
<p>La primera gran diferencia es que la herencia en JavaScript se realiza usando
llamadas de <em>cadenas de prototipo</em> (<em>prototype chains</em>).</p>
<aside>
<p><strong>Nota:</strong> Simplemente usando <code>Bar.prototype = Foo.prototype</code> dará lugar a dos objetos
que comparten el <strong>mismo</strong> prototipo. Por lo tanto, los cambios que se realicen en un
objeto afectará al otro objeto, así, en la mayoría de los casos no es el efecto
deseado.</p>
</aside>
<pre><code>function Foo() {
this.value = 42;
}
Foo.prototype = {
method: function() {}
};
function Bar() {}
// Asigna el prototipo de Bar como una nueva instancia de Foo
Bar.prototype = new Foo();
Bar.prototype.foo = 'Hello World';
// Asegura que el constructor sea Bar
Bar.prototype.constructor = Bar;
var test = new Bar() // crea una nueva instancia de Bar
// Resultado de cadena de prototipos (prototype chain)
test [instance of Bar]
Bar.prototype [instance of Foo]
{ foo: 'Hello World' }
Foo.prototype
{ method: ... }
Object.prototype
{ toString: ... /* etc. */ }
</code></pre>
<p>En el código anterior, el objeto <code>test</code> hereda de <code>Bar.prototype</code> y <code>Foo.prototype</code>;
por lo tanto, tendrá acceso a la función <code>method</code> que se ha definido en <code>Foo</code>.
También se tendrá acceso a a la propiedad <code>value</code> de la <strong>única</strong> instancia de <code>Foo</code>
que compone su prototipo. Es importante tomar en cuenta que <code>new Bar()</code> <strong>no</strong> creará una nueva
instancia de <code>Foo</code>, pero retornará lo asignado en su prototipo; de este modo, todas las instancias
de <code>Bar</code> tendrán que compartir el <strong>mismo</strong> <code>valor</code> de la propiedad.</p>
<aside>
<p><strong>Nota:</strong> <strong>No</strong> utilice <code>Bar.prototype = Foo</code>, ya que no apunta al prototipo
de <code>Foo</code>, sino al objeto de la función <code>Foo</code>. Así la cadena de prototipo
cambiará a <code>Function.prototype</code> y no a <code>Foo.prototype</code>;
Por lo tanto, el <code>método</code> no estará disponible en la cadena de prototipo.</p>
</aside>
</div><div><h3>Búsqueda de propiedades</h3>
<p>Cuando se accede a las propiedades de un objeto, JavaScript recorre la cadena de
prototipo hacia <strong>arriba</strong> hasta encontrar la propiedad con el nombre solicitado.</p>
<p>Cuando se llega al final de la cadena - concretamente <code>Object.prototype</code> - y aún
no se ha encontrado la propiedad especificada, se retornará un valor
<a href="#core.undefined">undefined</a> en su lugar.</p>
</div><div><h3>La propiedad prototype</h3>
<p>Aunque la propiedad prototype es usada por el lenguaje para construir la cadena
de prototipos, es posible asignar <strong>cualquier</strong> valor. Aunque los tipos primitivos
serán ignorados cuando se asigne en prototype.</p>
<pre><code>function Foo() {}
Foo.prototype = 1; // no tendrá efecto
</code></pre>
<p>La asignación de objetos, como se muestra en el ejemplo anterior, funcionará, y permitirá
la creación dinámica de cadena de prototipos.</p>
</div><div><h3>Rendimiento</h3>
<p>El tiempo tomado en la búsqueda de propiedades es alta y la cadena de prototipo puede
presentar un impacto negativo critico en el rendimiento en partes del código. Además,
si ha tratado de acceder a propiedades que no existen este saltara a la cadena de prototipo.</p>
<p>Además, al recorrer en <a href="#object.forinloop">iteración</a> las propiedades de un objeto
y <strong>cada</strong> propiedad será encontrada en la cadena de prototipo de manera ennumerada.</p>
</div><div><h3>Extensión de prototipos nativos</h3>
<p>Una mala característica que se suele utilizar para extender <code>Object.prototype</code> o cualquier
otro prototipo construido.</p>
<p>Esta técnica es conocida en inglés como <a href="http://en.wikipedia.org/wiki/Monkey_patch">monkey patching</a> ya que <em>encapsula</em> lo que se interrumpe en el código.
Si bien es utilizado en frameworks como <a href="http://prototypejs.org/">Prototype</a>, todavía no existen buenas razones para adoptarlo o integrarlo
como tipos de dato o como funcionalidad no estándar.</p>
<p>La <strong>única</strong> buena razón para extender un prototipo es acondicionarlo a nuevas
características en motores de JavaScript; por ejemplo,
<a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach"><code>Array.forEach</code></a>.</p>
</div><div><h3>En conclusión</h3>
<p>Se <strong>debe</strong> entender por completo el módelo de herencia prototipado antes de
escribir código complejo que lo utlilice. Además, observe la longitud de la
cadena de prototipo y modificala si es necesario para evitar posibles problemas de
rendimiento. Con relación a los prototipos nativos, estos <strong>nunca</strong> deben ser extendidos a
menos que sea para mantener la compatibilidad con nuevas características de JavaScript.</p></div></article><article id="object.hasownproperty"><h2><code>hasOwnProperty</code></h2><div><p>Con el fin de comprobar si un objeto posee una propiedad definida <em>en sí</em> mismo y <strong>no</strong>
en algún lugar de su <a href="#object.prototype">cadena de prototipo</a>, es necesario utilizar
el método <code>hasOwnProperty</code> ya que todos los objetos herendan de <code>Object.prototype</code>.</p>
<aside>
<p><strong>Nota:</strong> <strong>No</strong> es suficiente con comprobar si una propiedad está <code>definida</code>.
La propiedad bien podría existir, pero su valor sólo pasa a ser definido como
<code>undefined</code>.</p>
</aside>
<p><code>hasOwnProperty</code> es la única utilidad en JavaScript que se ocupa de las propiedades
y <strong>no</strong> las salta en la cadena de prototipo.</p>
<pre><code>// Envenenamiento en Object.prototype
Object.prototype.bar = 1;
var foo = {goo: undefined};
foo.bar; // 1
'bar' in foo; // true
foo.hasOwnProperty('bar'); // false
foo.hasOwnProperty('goo'); // true
</code></pre>
<p>Sólo <code>hasOwnProperty</code> retornará el resultado correcto y esperado, esto es
ensencial cuando se repite una iteración en las propiedades de cualquier objeto. No hay
otra maner de excluir las propiedades que no están definidas en el mismo objeto, pero
en alguna parte de su cadena de prototipo si.</p>
</div><div><h3><code>hasOwnProperty</code> como propiedad</h3>
<p>JavaScript <strong>no</strong> protege el nombre de la propiedad <code>hasOwnProperty</code>; de este modo, si existe
la posibilidad de que un objeto tenga una propiedad con el mismo nombre, es necesario utilizar
<code>hasOwnProperty</code> como propiedad <em>externa</em> con el fin de obtener resultados correctos.</p>
<pre><code>var foo = {
hasOwnProperty: function() {
return false;
},
bar: 'Here be dragons'
};
foo.hasOwnProperty('bar'); // siempre devolverá false
// Utilice otro objeto con hasOwnProperty y llamelo con 'this' para asignarlo a foo
({}).hasOwnProperty.call(foo, 'bar'); // true
</code></pre>
</div><div><h3>En conclusión</h3>
<p>Cuando se necesite comprobar la existencia de una propiedad en un objeto, <code>hasOwnProperty</code> es
el <strong>único</strong> método para hacerlo. También se recomienda el uso de <code>hasOwnProperty</code> como
parte de un <a href="#object.forinloop">bucle <code>for in</code></a>, esto evitará errores desde
extenciones de <a href="#object.prototype">prototipos</a> nativos.</p></div></article><article id="object.forinloop"><h2>El bucle <code>for in</code></h2><div><p>Al igual que el operador <code>in</code>, el bucle <code>for in</code> también recorre sobre la
cadena de prototipo cuando este se repite en una iteración en las propiedades de un objeto.</p>
<aside>
<p><strong>Nota:</strong> El bucle <code>for in</code> <strong>no</strong> se repetirá en cualquier propiedad que
tenga atributos <code>enumerables</code> asignados a <code>false</code>; por ejemplo, la propiedad
<code>length</code> de un array.</p>
</aside>
<pre><code>// Envenenamiento en Object.prototype
Object.prototype.bar = 1;
var foo = {moo: 2};
for(var i in foo) {
console.log(i); // Imprime ambos bar y moo
}
</code></pre>
<p>Dado que no es posible cambiar el comportamiento del bucle <code>for in</code> en sí mismo, es
necesario filtrar las propiedades internas no deseadas dentro del bucle,
esto se hace mediante el uso del método <a href="#object.hasownproperty"><code>hasOwnProperty</code></a> del
<code>Object.prototype</code>.</p>
<aside>
<p><strong>Nota:</strong> Dado que <code>for in</code> siempre recorre por completo la cadena de prototipo,
este se pondrá más lento con cada capa adicional que un objeto herede.</p>
</aside>
</div><div><h3>Usando <code>hasOwnProperty</code> para filtrado</h3>
<pre><code>// Aún es el foo del código de arriba
for(var i in foo) {
if (foo.hasOwnProperty(i)) {
console.log(i);
}
}
</code></pre>
<p>Está versión es la única forma correcta de uso. Esto se debe <strong>sólo</strong> al uso de
<code>hasOwnProperty</code> que imprimirá <code>moo</code>. Cuando <code>hasOwnProperty</code> se omita, el código es
propenso a errores en los casos de prototipos nativos - ej. <code>Object.prototype</code> -
se ha extendedido.</p>
<p>Uno de los frameworks más usado que implementa estas funcionalidades es <a href="http://www.prototypejs.org/">Prototype</a>. Cuando el
framework es incluido, el bucle <code>for in</code> que no utilicen <code>hasOwnProperty</code> no podrá garantizar que
se interrumpa.</p>
</div><div><h3>En conclusión</h3>
<p>Se recomienda utilizar <strong>siempre</strong> el uso de <code>hasOwnProperty</code>. Nunca debe suponer <br />
ningún entorno donde el código se ejecute, o si los prototipos
nativos han sido extendidos o no. </p></div></article></section><section id="function"><!-- Introduction--><header id="function.intro"><h1>Funciones</h1></header><!-- Articles--><article id="function.general"><h2>La declaración de funciones y expresiones</h2><div><p>Las funciones en JavaScript son las primeras clases de objetos. Esto significa que se
puede pasar como cualquier otro valor. Un uso común de está característica es pasar de
una <em>función anónima</em> a otra, posiblemente una función asíncrona. Esto se conoce como <code>callback</code>.</p>
</div><div><h3>La declaración <code>function</code></h3>
<pre><code>function foo() {}
</code></pre>
<p>La función anterior se <a href="#function.scopes">carga</a> así mismo antes de iniciar la ejecución del
programa; por lo tanto, está disponible en <em>todo</em> el scope (ámbito) de la aplicación
donde se ha <em>definido</em>, aunque hubiera sido llamado antes de definirse en el código.</p>
<pre><code>foo(); // Funciona porque foo ha sido creado antes que este código se ejecute
function foo() {}
</code></pre>
</div><div><h3>La expresión <code>function</code></h3>
<pre><code>var foo = function() {};
</code></pre>
<p>Este ejemplo asigna una función sin nombre y anónima a la variable <code>foo</code>. </p>
<pre><code>foo; // 'undefined'
foo(); // Lanza TypeError
var foo = function() {};
</code></pre>
<p>Debido a la declaración de <code>var</code>, que carga el nombre de la variable <code>foo</code> antes
de la ejecución real del inicio del código, <code>foo</code> ya estará definidido cuando se
ejecute el script.</p>
<p>Pero se asigna sólo si ocurre en tiempo de ejecución, el valor de <code>foo</code> de forma
predetermina es <a href="#core.undefined">undefined</a> antes de que el código se ejecute.</p>
</div><div><h3>Expresión nombre de función</h3>
<p>Otro caso especial de asignación de nombre de funciones.</p>
<pre><code>var foo = function bar() {
bar(); // Funciona
}
bar(); // ReferenceError
</code></pre>
<p>Aquí <code>bar</code> no está disponible en el ámbito externo (scope), ya que la función sólo es
asignada a <code>foo</code>; Sin embargo, dentro de <code>bar</code> si está disponible. Esto se debe a la forma
en como trabaja la <a href="#function.scopes">resolución de nombres</a> en JavaScript, el nombre de
la función esta <em>siempre</em> disponible en el ámbito local de la propia función.</p></div></article><article id="function.this"><h2>Cómo trabaja <code>this</code></h2><div><p>JavaScript tiene un concepto diferente sobre el nombre especial <code>this</code> referido a la
mayoría de lenguajes de programación. Hay exactamente <strong>cinco</strong> formas distintas en donde
es posible ver el valor de <code>this</code> dentro de lo posible en el lenguaje.</p>
</div><div><h3>El ámbito global (Global Scope)</h3>
<pre><code>this;
</code></pre>
<p>Cuando se utiliza <code>this</code> en el ámbito global, simplemente se refiere al objeto <em>global</em>.</p>
</div><div><h3>Llamar a una función</h3>
<pre><code>foo();
</code></pre>
<p>Aquí <code>this</code> se refiere al objeto <em>global</em>.</p>
<aside>
<p><strong>Nota ES5:</strong> En modo estricto (strict mode), global <strong>ya no</strong> existe.
<code>this</code> tendrá el valor de <code>undefined</code> en este caso.</p>
</aside>
</div><div><h3>Llamar a un método</h3>
<pre><code>test.foo();
</code></pre>
<p>En este ejemplo <code>this</code> se referiere a <code>test</code>.</p>
</div><div><h3>Llamar a un constructor</h3>
<pre><code>new foo();
</code></pre>
<p>Llamar a una función que esta precedida por la palabra clave <code>new</code> actúa como
un <a href="#function.constructors">constructor</a>. Dentro de la función, <code>this</code> se refiere
al <code>Objeto</code> <em>recién creado</em>.</p>
</div><div><h3>Ajuste explícito de <code>this</code></h3>
<pre><code>function foo(a, b, c) {}
var bar = {};
foo.apply(bar, [1, 2, 3]); // array que se apilará
foo.call(bar, 1, 2, 3); // resultados a = 1, b = 2, c = 3
</code></pre>
<p>Cuando se utiliza los métodos <code>call</code> o <code>apply</code> en <code>Function.prototype</code>, el valor de
<code>this</code> dentro de la función llamada se ajustará <strong>explícitamente</strong> al primer argumento
correspondiente a la llamada de la función.</p>
<p>Como resultado, el ejemplo anterior sobre los <em>casos de métodos</em> estos <strong>no</strong> se aplican, y <code>this</code>
dentro de <code>foo</code> puede establecerse en <code>bar</code>.</p>
<aside>
<p><strong>Nota:</strong> <code>this</code> <strong>no puede</strong> ser usado para referirse a un objeto dentro de un <code>Objeto</code>
literal. Así <code>var obj = {me: this}</code> <strong>no</strong> dará ninǵun resultado en <code>me</code> refiriendose a
<code>obj</code>, ya que <code>this</code> sólo será obtenido por uno de los cincos casos enumerados.</p>
</aside>
</div><div><h3>Errores comunes</h3>
<p>Si bien en la mayoría de los casos esto tiene sentido, el primero puede cosiderarse como otro
mal diseño del lenguaje, ya que <strong>nunca</strong> tiene un uso práctico.</p>
<pre><code>Foo.method = function() {
function test() {
// this es establecido como un objeto global
}
test();
}
</code></pre>
<p>Un error común es que <code>this</code> dentro de <code>test</code> haga referencia a <code>Foo</code>, mientras que en
realidad esto <strong>no es así</strong>.</p>
<p>Con el fin de acceder a <code>Foo</code> desde dentro de <code>test</code> es necesario crear una variable local
dentro del <code>método</code> para referirse a <code>Foo</code>.</p>
<pre><code>Foo.method = function() {
var that = this;
function test() {
// Use that instead of this here
}
test();
}
</code></pre>
<p><code>that</code> es justo un nombre normal, pero es comúnmente usado para referenciar a <code>this</code>
de forma externa. En combinación con <a href="#function.closures">closures</a>, esto puede ser
también usado para pasar <code>this</code> como valor.</p>
</div><div><h3>Asignación de métodos</h3>
<p>Otra cosa que <strong>no</strong> funciona en JavaScript son los alias en las funciones, es decir,
<strong>asignar</strong> un método a una variable.</p>
<pre><code>var test = someObject.methodTest;
test();
</code></pre>
<p>Debido al primer caso, <code>test</code> actúa como una función de llamada; por lo que
<code>this</code> dentro de este no estará referido a <code>someObject</code>.</p>
<p>Mientras que la unión de <code>this</code> puede parecer una mala idea en un principio, esto es en
realidad lo que hace trabajar a la <a href="#object.prototype">herencia de prototipo</a>. </p>
<pre><code>function Foo() {}
Foo.prototype.method = function() {};
function Bar() {}
Bar.prototype = Foo.prototype;
new Bar().method();
</code></pre>
<p>Cuando los <code>métodos</code> son llamados desde una instancia de <code>Bar</code>, <code>this</code> se referirá a una
instancia.</p></div></article><article id="function.closures"><h2>Closures y referencias</h2><div><p>Una de las características más poderosas de JavaScript es la disponibilidad de <em>closures</em> (cerraduras),
esto significa que los ámbitos <strong>siempre</strong> podrán ser accedidos por ámbitos externos donde
fueron definidos. Dado que sólo el alcance es único en JavaScript en el
<a href="#function.scopes">ámbito de la función</a>, todas las funciones, por omisión, actúan como closures.</p>
</div><div><h3>Emulando variables privadas</h3>
<pre><code>function Counter(start) {
var count = start;
return {
increment: function() {
count++;
},
get: function() {
return count;
}
}
}
var foo = Counter(4);
foo.increment();
foo.get(); // 5
</code></pre>
<p>En este caso, <code>Counter</code> retorna <strong>dos</strong> closures. La función <code>increment</code> y la
función <code>get</code>. Ambas funciones mantienen el ámbito de la <strong>referencia</strong> de <br />
<code>Counter</code> y, por lo tanto, siempre accede a la variable <code>count</code> que fue definido
en el ámbito.</p>
</div><div><h3>¿Por qué las variables privadas trabajan?</h3>
<p>Dado que no es posible referenciar o asignar ámbitos en JavaScript, <strong>no</strong> hay
manera de acceder a la variable <code>count</code> desde fuera. Sólo existe una forma para
interactuar con estos vía los dos closures.</p>
<pre><code>var foo = new Counter(4);
foo.hack = function() {
count = 1337;
};
</code></pre>
<p>El código anterior <strong>no</strong> ha cambiado la variable <code>count</code> en el ámbito de <code>Counter</code>,
desde <code>foo.hack</code> no es definido en <strong>ese</strong> ámbito. En su lugar se creará - o
se anulará - la variable <em>global</em> <code>count</code>.</p>
</div><div><h3>Closures dentro de bucles</h3>
<p>Un error frecuente en el uso de closures dentro de bucles, es como si se tratará
de copiar el valor del índice de la variable del bucle.</p>
<pre><code>for(var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
</code></pre>
<p>El código anterior <strong>no</strong> tendrá como salida los números del <code>0</code> al <code>9</code>, sino
simplementemente se imprimirá el número <code>10</code> diez veces.</p>
<p>La función <em>anónima</em> hace <strong>referencia</strong> a <code>i</code> y se llama a
<code>console.log</code>, el <code>bucle for</code> ya ha terminado y finalizo el valor de
<code>i</code> a <code>10</code>.</p>
<p>Con el fin de obtener el comportamiento deseado, es necesario crear una <strong>copia</strong>
del valor de <code>i</code>.</p>
</div><div><h3>Evitando el problema de referencia</h3>
<p>Con el fin de copiar el valor de la variable índice del bucle, lo mejor es utilizar
un <a href="#function.scopes">contenedor anónimo</a>.</p>
<pre><code>for(var i = 0; i < 10; i++) {
(function(e) {
setTimeout(function() {
console.log(e);
}, 1000);
})(i);
}
</code></pre>
<p>La función anónima externa llamará inmediatamente a <code>i</code> como su primer
argumento y recibirá la copia del <strong>valor</strong> de <code>i</code> como parámetro de <code>e</code>.</p>
<p>La función anónima que se pasa a <code>setTimeout</code> ahora es una referencia a
<code>e</code>, cuyo valor <strong>no</strong> han sido cambiados por el bucle.</p>
<p>No hay otra manera de lograr esto; se debe retornar una función desde
el contenedor anónimo, que tendrá el mismo comportamiento que el código
anterior.</p>
<pre><code>for(var i = 0; i < 10; i++) {
setTimeout((function(e) {
return function() {
console.log(e);
}
})(i), 1000)
}
</code></pre></div></article><article id="function.arguments"><h2>El objeto <code>arguments</code></h2><div><p>Cada ámbito de la función de JavaScript puede acceder a la variable especial <code>arguments</code>.
Está variable contiene una lista de todos los argumentos que se pasan a la función.</p>
<aside>
<p><strong>Nota:</strong> En este caso <code>arguments</code> ya se ha definido dentro del ámbito de la
función ya sea através de la sentencia <code>var</code> o como un parámetro formal,
el objeto <code>arguments</code> no se creará.</p>
</aside>
<p>El objeto <code>arguments</code> <strong>no</strong> es un <code>Array</code>. Si bien cuenta con la semántica
de un array - concretamente la propiedad <code>length</code> - no hereda de
<code>Array.prototype</code> y es de hecho un <code>Objeto</code>.</p>
<p>Debido a esto, <strong>no</strong> es posible usar los métodos estándar de los arrays como <code>push</code>,
<code>pop</code> o <code>slice</code> en <code>arguments</code>. Mientras que la iteración es un simple bucle <code>for</code> que
funciona muy bien, esto se convierte necesariamente en un <code>Array</code> real con el
fin de utilizar los métodos de un <code>Array</code>.</p>
</div><div><h3>Conversión de un Array</h3>
<p>El siguiente código devuelve un nuevo <code>Array</code> que contiene todos los elementos del
objeto <code>arguments</code>.</p>
<pre><code>Array.prototype.slice.call(arguments);
</code></pre>
<p>Esta conversión es <strong>lenta</strong>, <strong>no es recomendable</strong> usarlo en puntos criticos que
afecten el rendimiento del código.</p>
</div><div><h3>Pasar Argumentos</h3>
<p>El siguiente método es recomendado para pasar argumentos desde una función a
otra.</p>
<pre><code>function foo() {
bar.apply(null, arguments);
}
function bar(a, b, c) {
// do stuff here
}
</code></pre>
<p>Otro truco es utilizar tanto <code>call</code> y <code>apply</code> juntos para crear contenedores rápidos y
consolidados.</p>
<pre><code>function Foo() {}
Foo.prototype.method = function(a, b, c) {
console.log(this, a, b, c);
};
// Crea una versión sin consolidar de "method"
// Se toma los parámetros: this, arg1, arg2...argN
Foo.method = function() {
// Resultado: Foo.prototype.method.call(this, arg1, arg2... argN)
Function.call.apply(Foo.prototype.method, arguments);
};
</code></pre>
</div><div><h3>Los parámetros formales y argumentos de índices</h3>
<p>El objeto <code>arguments</code> crea las funciones de <em>getter</em> y <em>setter</em> para sus
propiedades, así como parámetros formales de la función.</p>
<p>Como resultado, se ha cambiado el valor formal del parámetro también se cambio el
valor de la propiedad correspondiente del objeto <code>arguments</code>, y al revés.</p>
<pre><code>function foo(a, b, c) {
arguments[0] = 2;
a; // 2
b = 4;
arguments[1]; // 4
var d = c;
d = 9;
c; // 3
}
foo(1, 2, 3);
</code></pre>
</div><div><h3>Mitos y verdades sobre el rendimiento</h3>
<p>El objeto <code>arguments</code> es siempre creado con las dos únicas excepciones cuando es
el caso en que declarado como un nombre dentro de la función o uno de los
parámetros formales. No importa si se utiliza o no.</p>
<p>Ambos <em>getters</em> y <em>setters</em> son <strong>siempre</strong> creados; por lo tanto, con que casi no se
tiene un impacto en el rendimiento en todo, especialemente no en el código real donde no
es más que un simple acceso a las propiedades del objeto <code>arguments</code>.</p>
<aside>
<p><strong>Nota ES5:</strong> Estos <em>getters</em> y <em>setters</em> no son creados en modo estricto.</p>
</aside>
<p>Sin embargo, hay casos en que se reducirá drásticamente el rendimiento en los motores
modernos de JavaScript. Este es el caso del uso de <code>arguments.callee</code>.</p>
<pre><code>function foo() {
arguments.callee; // realiza algo con la función del objeto
arguments.callee.caller; // y llama a la función del objeto
}
function bigLoop() {
for(var i = 0; i < 100000; i++) {
foo(); // Debería ser normalmente entre líneas...
}
}
</code></pre>
<p>El código anterior, <code>foo</code> no puede estar sujeto a la <a href="http://en.wikipedia.org/wiki/Inlining">expansión en línea</a> ya que se
necesita saber acerca de sí mismo y la llamada. Esto no sólo denota los posibles beneficios
de rendimiento que surgen con la expansión en línea, ya que también interrumpe la encapsulación
ya que la función ahora puede ser dependiente de un contexto específico de llamada.</p>
<p>Es <strong>muy recomendable</strong> <strong>nunca</strong> hacer uso de <code>arguments.callee</code> o de cualquier
de sus propiedades.</p>
<aside>
<p><strong>Nota ES5:</strong> En modo estricto, <code>arguments.callee</code> generará una excepción de <code>TypeError</code> ya que
su uso ha quedado obsoleto.</p>
</aside></div></article><article id="function.constructors"><h2>Constructores</h2><div><p>Los constructores en JavaScript todavía son diferentes a los de otros lenguajes.
Cualquier llamada que es precedida por la palabra <code>new</code> actua como un constructor.</p>
<p>Dentro del constructor - la función llama - el valor de <code>this</code> se refiere a un
<code>Objeto</code> recién creado. El <a href="#object.prototype"><code>prototipo</code></a> de este <strong>nuevo</strong>
objeto se establece en el <code>prototipo</code> de la funcióno que es invocado como el
constructor.</p>
<p>Si la función que se llama no tiene una sentencia <code>return</code> explícita, entonces
implícitamente devuelve el valor de <code>this</code> - el nuevo objeto. </p>
<pre><code>function Foo() {
this.bla = 1;
}
Foo.prototype.test = function() {
console.log(this.bla);
};
var test = new Foo();
</code></pre>
<p>La llamada de <code>Foo</code> por encima del constructor y establece el <code>prototipo</code> del objeto
recién creado a <code>Foo.prototype</code>.</p>
<p>En caso explícito de la sentencia <code>return</code> de la función devuelva el valor especificado
que la declaración, <strong>pero sólo</strong> si el valor devuelto es un <code>Object</code>. </p>
<pre><code>function Bar() {
return 2;
}
new Bar(); // a new object
function Test() {
this.value = 2;
return {
foo: 1
};
}
new Test(); // the returned object
</code></pre>
<p>Cuando una <code>nueva</code> keyword es omitidad, la función <strong>no</strong> devuelve un nuevo objeto. </p>
<pre><code>function Foo() {
this.bla = 1; // se establece en el objeto global
}
Foo(); // undefined
</code></pre>
<p>Auqnue el ejemplo anterior puede parecer que trabaja en algunos casos, debido
a los trabajos de <a href="#function.this"><code>this</code></a> en JavaScript, que usará el
<em>objeto global</em> como valor de <code>this</code>.</p>
</div><div><h3>Fábricas</h3>
<p>Con el fin de ser capaz de omitir un <code>nuevo</code> keyword, la función del tiene
explícitamente devolver un valor.</p>
<pre><code>function Bar() {
var value = 1;
return {
method: function() {
return value;
}
}
}
Bar.prototype = {
foo: function() {}
};
new Bar();
Bar();
</code></pre>
<p>Ambos llamadas a <code>Bar</code> devuelven exactamente lo mismo, un reciente objeto creado que
tiene como propiedad llamada el <code>method</code>, esto es un
<a href="#function.closures">Closure</a>.</p>
<p>También hay que notar que la llamada <code>new Bar()</code> <strong>no</strong> afecta al prototipo
del objeto devuelto. Mientras que el prototipo se establece en el objeto recién creado,
<code>Bar</code> nunca devuelve un nuevo objeto.</p>
<p>En el ejemplo anterior, no hay diferencia funcional entre usar y no usar
el keyword <code>new</code>.</p>
</div><div><h3>Creación de nuevos objetos vía Factorias</h3>
<p>Una recomendación a menudo es <strong>no</strong> utilizar <code>new</code> ya que su uso puede
conducir a errores.</p>
<p>Con el fin de crear un nuevo objeto, uno bien debe utilizar una fábrica y un
constructor para crear un nuevo objeto dentro de la fábrica.</p>
<pre><code>function Foo() {
var obj = {};
obj.value = 'blub';
var private = 2;
obj.someMethod = function(value) {
this.value = value;
}
obj.getPrivate = function() {
return private;
}
return obj;
}
</code></pre>
<p>Aunque lo anterior es robuesto frente a la keyword <code>new</code> y, ciertamente hace
que el uso de <a href="#function.closures">variables privadas</a> sea fácil, esto viene con
algunas desventajas.</p>
<ol>
<li>Se utiliza más memoria, ya que los objetos creados <strong>no</strong> comparten los métodos de
un prototipo.</li>
<li>Con el fin de heredar de una fábrica se necesita copiar todos los métodos a otro
objeto o poner todo en un prototipo de nuevo objeto.</li>
<li>La eliminación de una cadena de prototipo sólo por dejar la keyword <code>new</code> de
alguna manera va en contra del espíritu del lenguaje.</li>
</ol>
</div><div><h3>En conclusión</h3>
<p>Mientras que se omite el keyword <code>new</code> podría dar a errores, <strong>no</strong> es ciertamente
una razón para abandonar el uso de prototipos por completo. Al final todo se reduce a
la solución que se adapta mejor a las necesidades de la aplicación, especialmente si es
importante elegir un estilo específico en la creación de objetos
<strong>y resistirse</strong>.</p></div></article><article id="function.scopes"><h2>Ámbitos y Namespaces</h2><div><p>A pesar que JavaScript tiene una muy buena sintaxis de dos llaves para los bloques,
está <strong>no</strong> es compatible con el soporte de ámbito de bloques; por lo que todo se deja
al lenguaje con el <em>ámbito de la función</em>.</p>
<pre><code>function test() { // un ámbito
for(var i = 0; i < 10; i++) { // no es un ámbito
// cuenta
}
console.log(i); // 10
}
</code></pre>
<aside>
<p><strong>Nota:</strong> Cuando no use una instrucción, de retorno o una función como
argumento, la notación de <code>{...}</code> serán interpretadas como una declaración de bloques y
<strong>no</strong> como un objeto literal. Esto, en conjunto con la
<a href="#core.semicolon">inserción automática de punto y coma</a>, puede conducir a errores sutiles.</p>
</aside>
<p>Tampoco hay distintos namespaces en JavaScript, lo que significa que todo se define
en un namespace <em>global y compartido</em>.</p>
<p>Cada vez que una variable es referenciada, JavaScript recorre hacia arriba a través de todos
los ámbitos hasta encontrarlo. En este caso que llegue al ámbito global y todavía no ha
encontrado el nombre solicitado, se generará un error <code>ReferenceError</code>.</p>
</div><div><h3>El terror de las variables globales</h3>
<pre><code>// script A
foo = '42';
// script B
var foo = '42'
</code></pre>
<p>Estos dos scripts <strong>no</strong> tienen el mismo efecto. El script A define una variable
llamada <code>foo</code> en el ámbito <em>global</em> y el script B define <code>foo</code> en el
<em>actual</em> ámbito.</p>
<p>Una vez más, esto <strong>no</strong> tiene el <em>mismo efecto</em> para todo, no usar <code>var</code> puede tener
mayor implicación.</p>
<pre><code>// ámbito global
var foo = 42;
function test() {
// ámbito local
foo = 21;
}
test();
foo; // 21
</code></pre>
<p>Dejando de lador la sentencia <code>var</code> dentro de la función <code>test</code> sobre escribiría el
valor de <code>foo</code>. Si bien al principio puede parecer un gran cambio, se tiene
miles de líneas de código en JavaScript y no se usaría <code>var</code> introduciendose en un
horrible y difícil detección de errores.</p>
<pre><code>// ámbito global
var items = [/* some list */];
for(var i = 0; i < 10; i++) {
subLoop();
}
function subLoop() {
// ámbito de subLoop
for(i = 0; i < 10; i++) { // falta la sentencia var
// ¡realizar cosas asombrosas!
}
}
</code></pre>
<p>El bucle externo terminará después de la primera llamada a <code>subLoop</code>, desde <code>subLoop</code>
sobreescribe el valor global de <code>i</code>. Usando <code>var</code> para el segundo bucle <code>for</code> se hace
fácil evitar este error. La sentencia <code>var</code> no debe <strong>nunca</strong> dejarse a menos que
el <em>efecto deseado</em> es afectado por el ámbito exteriror.</p>
</div><div><h3>Variables locales</h3>
<p>La única fuente para las variables locales en JavaScript son los parámetros de la
<a href="#function.general">función</a> y variables que fueron declaradas vía la sentencia
<code>var</code>.</p>
<pre><code>// ámbito global
var foo = 1;
var bar = 2;
var i = 2;
function test(i) {
// ámbito local de la función test
i = 5;
var foo = 3;
bar = 4;
}
test(10);
</code></pre>
<p>Mientras <code>foo</code> y <code>i</code> son variables locales dentro del ámbitor de la función <code>test</code>,
ela asignación de <code>bar</code> sobreescribe la variable global con el mismo nombre.</p>
</div><div><h3>Hoisting</h3>
<p>La declaración de <strong>hoists</strong> en JavaScript. Esto significa que tanto la declaración de <code>var</code> y
la <code>función</code> declarada se translada a la parte superior de su ámbito que lo contiene.</p>
<pre><code>bar();
var bar = function() {};
var someValue = 42;
test();
function test(data) {
if (false) {
goo = 1;
} else {
var goo = 2;
}
for(var i = 0; i < 100; i++) {
var e = data[i];
}
}
</code></pre>
<p>El código anterior transforma antes de ejecutarse. JavaScript mueve
la declaracione <code>var</code> aspi como las declaraciones de la <code>función</code> a la parte superior a
lo más cercano del ámbito circundante.</p>
<pre><code>// declaraciones var movidas aquí