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
1981 lines (1488 loc) · 82.4 KB
/
index.html
File metadata and controls
1981 lines (1488 loc) · 82.4 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="en"><head><title>JavaScript Garden</title><meta charset="utf-8"><meta name="description" content="A Guide to JavaScript's Quirks and Flaws."><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 class="active"><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><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">Intro</a></h1><ul></ul></li><li class="nav_object"><h1><a href="#object">Objects</a></h1><ul><li><a href="#object.general">Object Usage and Properties</a></li><li><a href="#object.prototype">The Prototype</a></li><li><a href="#object.hasownproperty"><code>hasOwnProperty</code></a></li><li><a href="#object.forinloop">The <code>for in</code> Loop</a></li></ul></li><li class="nav_function"><h1><a href="#function">Functions</a></h1><ul><li><a href="#function.general">Function Declarations and Expressions</a></li><li><a href="#function.this">How <code>this</code> Works</a></li><li><a href="#function.closures">Closures and References</a></li><li><a href="#function.arguments">The <code>arguments</code> Object</a></li><li><a href="#function.constructors">Constructors</a></li><li><a href="#function.scopes">Scopes and Namespaces</a></li></ul></li><li class="nav_array"><h1><a href="#array">Arrays</a></h1><ul><li><a href="#array.general">Array Iteration and Properties</a></li><li><a href="#array.constructor">The <code>Array</code> Constructor</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">Core</a></h1><ul><li><a href="#core.eval">Why Not to Use <code>eval</code></a></li><li><a href="#core.undefined"><code>undefined</code> and <code>null</code></a></li><li><a href="#core.semicolon">Automatic Semicolon Insertion</a></li><li><a href="#core.delete">The <code>delete</code> Operator</a></li></ul></li><li class="nav_other"><h1><a href="#other">Other</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>Intro</h1><div><p><strong>JavaScript Garden</strong> is a growing collection of documentation about the most
quirky parts of the JavaScript programming language. It gives advice to
avoid common mistakes and subtle bugs, as well as performance issues and bad
practices, that non-expert JavaScript programmers may encounter on their
endeavours into the depths of the language.</p>
<p>JavaScript Garden does <strong>not</strong> aim to teach you JavaScript. Former knowledge
of the language is strongly recommended in order to understand the topics covered
in this guide. In order to learn the basics of the language, please head over to
the excellent <a href="https://developer.mozilla.org/en/JavaScript/Guide">guide</a> on the Mozilla Developer Network.</p>
<h2>The Authors</h2>
<p>This guide is the work of two lovely <a href="http://stackoverflow.com/">Stack Overflow</a> users, <a href="http://stackoverflow.com/users/170224/ivo-wetzel">Ivo Wetzel</a>
(Writing) and <a href="http://stackoverflow.com/users/313758/yi-jiang">Zhang Yi Jiang</a> (Design).</p>
<h2>Contributors</h2>
<ul>
<li><a href="https://github.com/caio">Caio Romão</a> (Spelling corrections)</li>
<li><a href="https://github.com/blixt">Andreas Blixt</a> (Language corrections)</li>
</ul>
<h2>Hosting</h2>
<p>JavaScript Garden is hosted on GitHub, but <a href="http://cramerdev.com/">Cramer Development</a> supports us
with a mirror at <a href="http://javascriptgarden.info/">JavaScriptGarden.info</a>.</p>
<h2>License</h2>
<p>JavaScript Garden is published under the <a href="https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE">MIT license</a> and hosted on
<a href="https://github.com/BonsaiDen/JavaScript-Garden">GitHub</a>. If you find errors or typos please <a href="https://github.com/BonsaiDen/JavaScript-Garden/issues">file an issue</a> or a pull
request on the repository. You can also find us in the <a href="http://chat.stackoverflow.com/rooms/17/javascript">JavaScript room</a> on
Stack Overflow chat.</p></div></header><!-- Articles--></section><section id="object"><!-- Introduction--><header id="object.intro"><h1>Objects</h1></header><!-- Articles--><article id="object.general"><h2>Object Usage and Properties</h2><div><p>Everything in JavaScript acts like an object, with the only two exceptions being
<a href="#core.undefined"><code>null</code></a> and <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>A common misconception is that number literals cannot be used as
objects. That is because a flaw in JavaScript's parser tries to parse the <em>dot
notation</em> on a number as a floating point literal.</p>
<pre><code>2.toString(); // raises SyntaxError
</code></pre>
<p>There are a couple of workarounds which can be used in order make number
literals act as objects too.</p>
<pre><code>2..toString(); // the second point is correctly recognized
2 .toString(); // note the space left to the dot
(2).toString(); // 2 is evaluated first
</code></pre>
</div><div><h3>Objects as a Data Type</h3>
<p>Objects in JavaScript can also be used as a <a href="http://en.wikipedia.org/wiki/Hashmap"><em>Hashmap</em></a>; they mainly consist
of named properties mapping to values.</p>
<p>Using a object literal - <code>{}</code> notation - it is possible to create a
plain object. This new object <a href="#object.prototype">inherits</a> from <code>Object.prototype</code> and
has no <a href="#object.hasownproperty">own properties</a> defined on it.</p>
<pre><code>var foo = {}; // a new empty object
// a new object with a property called 'test' with value 12
var bar = {test: 12};
</code></pre>
</div><div><h3>Accessing Properties</h3>
<p>The properties of an object can be accessed in two ways, via either the dot
notation or the square bracket notation.</p>
<pre><code>var foo = {name: 'Kitten'}
foo.name; // kitten
foo['name']; // kitten
var get = 'name';
foo[get]; // kitten
foo.1234; // SyntaxError
foo['1234']; // works
</code></pre>
<p>Both notations are identical in their workings, with the only difference being that
the square bracket notation allows for dynamic setting of properties, as well as
the use of property names that would otherwise lead to a syntax error.</p>
</div><div><h3>Deleting Properties</h3>
<p>The only way to actually remove a property from an object is to use the <code>delete</code>
operator; setting the property to <code>undefined</code> or <code>null</code> only removes the
<em>value</em> associated with the property, but not the <em>key</em>.</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>The above outputs both <code>bar undefined</code> and <code>foo null</code> - only <code>baz</code> was
removed and is therefore missing from the output.</p>
</div><div><h3>Notation of Keys</h3>
<pre><code>var test = {
'case': 'I am a keyword, so I must be notated as a string',
delete: 'I am a keyword, so me too' // raises SyntaxError
};
</code></pre>
<p>Object properties can be both notated as plain characters and as strings. Due to
another mis-design in JavaScript's parser, the above will throw
a <code>SyntaxError</code> prior to ECMAScript 5.</p>
<p>This error arises from the fact that <code>delete</code> is a <em>keyword</em>; therefore, it must be
notated as a <em>string literal</em> to ensure that it will be correctly interpreted by
older JavaScript engines.</p></div></article><article id="object.prototype"><h2>The Prototype</h2><div><p>JavaScript does not feature a classical inheritance model; instead, it uses a
<em>prototypal</em> one. </p>
<p>While this is often considered to be one of JavaScript's weaknesses, the
prototypal inheritance model is in fact more powerful than the classic model.
It is, for example, fairly trivial to build a classic model on top of it, while the
other way around is a far more difficult task.</p>
<p>Due to the fact that JavaScript is basically the only widely used language that
features prototypal inheritance, it takes some time to adjust to the
differences between the two models. </p>
<p>The first major difference is that inheritance in JavaScript is done by using so
called <em>prototype chains</em>.</p>
<aside>
<p><strong>Note:</strong> Simply using <code>Bar.prototype = Foo.prototype</code> will result in both objects
sharing the <strong>same</strong> prototype. Therefore, changes to either object's prototype
will affect the prototype of the other as well, which in most cases is not the
desired effect.</p>
</aside>
<pre><code>function Foo() {
this.value = 42;
}
Foo.prototype = {
method: function() {}
};
function Bar() {}
// Set Bar's prototype to a new instance of Foo
Bar.prototype = new Foo();
Bar.prototype.foo = 'Hello World';
// Make sure to list Bar as the actual constructor
Bar.prototype.constructor = Bar;
var test = new Bar() // create a new bar instance
// The resulting prototype chain
test [instance of Bar]
Bar.prototype [instance of Foo]
{ foo: 'Hello World' }
Foo.prototype
{ method: ... }
Object.prototype
{ toString: ... /* etc. */ }
</code></pre>
<p>In the above, the object <code>test</code> will inherit from both <code>Bar.prototype</code> and
<code>Foo.prototype</code>; hence, it will have access to the function <code>method</code> that was
defined on <code>Foo</code>. It will also have access to the property <code>value</code> of the
<strong>one</strong> <code>Foo</code> instance that is its prototype. It is important to note that <code>new
Bar()</code> does <strong>not</strong> create a new <code>Foo</code> instance, but reuses the one assigned to
its prototype; thus, all <code>Bar</code> instances will share the <strong>same</strong> <code>value</code> property.</p>
<aside>
<p><strong>Note:</strong> Do <strong>not</strong> use <code>Bar.prototype = Foo</code>, since it will not point to
the prototype of <code>Foo</code> but rather to the function object <code>Foo</code>. So the
prototype chain will go over <code>Function.prototype</code> and not <code>Foo.prototype</code>;
therefore, <code>method</code> will not be on the prototype chain.</p>
</aside>
</div><div><h3>Property Lookup</h3>
<p>When accessing the properties of an object, JavaScript will traverse the
prototype chain <strong>upwards</strong> until it finds a property with the requested name.</p>
<p>When it reaches the top of the chain - namely <code>Object.prototype</code> - and still
hasn't found the specified property, it will return the value
<a href="#core.undefined">undefined</a> instead.</p>
</div><div><h3>The Prototype Property</h3>
<p>While the prototype property is used by the language to build the prototype
chains, it is still possible to assign <strong>any</strong> given value to it. However,
primitives will simply get ignored when assigned as a prototype.</p>
<pre><code>function Foo() {}
Foo.prototype = 1; // no effect
</code></pre>
<p>Assigning objects, as shown in the example above, will work, and allows for dynamic
creation of prototype chains.</p>
</div><div><h3>Performance</h3>
<p>The lookup time for properties that are high up on the prototype chain can have a
negative impact on performance critical sections of code. Additionally, trying to
access non-existent properties will always traverse the full prototype chain. </p>
<p>Also, when <a href="#object.forinloop">iterating</a> over the properties of an object
<strong>every</strong> property that is on the prototype chain will get enumerated.</p>
</div><div><h3>Extension of Native Prototypes</h3>
<p>One mis-feature that is often used is to extend <code>Object.prototype</code> or one of the
other built in prototypes.</p>
<p>This technique is called <a href="http://en.wikipedia.org/wiki/Monkey_patch">monkey patching</a> and breaks <em>encapsulation</em>. While
used by widely spread frameworks such as <a href="http://prototypejs.org/">Prototype</a>, there is still no good
reason for cluttering built-in types with additional <em>non-standard</em> functionality.</p>
<p>The <strong>only</strong> good reason for extending a built-in prototype is to backport
the features of newer JavaScript engines; for example,
<a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach"><code>Array.forEach</code></a>.</p>
</div><div><h3>In Conclusion</h3>
<p>It is a <strong>must</strong> to understand the prototypal inheritance model completely
before writing complex code which makes use of it. Also, watch the length of
the prototype chains and break them up if necessary to avoid possible
performance issues. Further, the native prototypes should <strong>never</strong> be extended
unless it is for the sake of compatibility with newer JavaScript features.</p></div></article><article id="object.hasownproperty"><h2><code>hasOwnProperty</code></h2><div><p>In order to check whether a object has a property defined on <em>itself</em> and <strong>not</strong>
somewhere on its <a href="#object.prototype">prototype chain</a>, it is necessary to use the
<code>hasOwnProperty</code> method which all objects inherit from <code>Object.prototype</code>.</p>
<aside>
<p><strong>Note:</strong> It is <strong>not</strong> enough to check whether a property is <code>undefined</code>. The
property might very well exist, but its value just happens to be set to
<code>undefined</code>.</p>
</aside>
<p><code>hasOwnProperty</code> is the only thing in JavaScript which deals with properties and
does <strong>not</strong> traverse the prototype chain.</p>
<pre><code>// Poisoning 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>Only <code>hasOwnProperty</code> will give the correct and expected result; this is
essential when iterating over the properties of any object. There is <strong>no</strong> other
way to exclude properties that are not defined on the object <em>itself</em>, but
somewhere on its prototype chain. </p>
</div><div><h3><code>hasOwnProperty</code> as a Property</h3>
<p>JavaScript does <strong>not</strong> protect the property name <code>hasOwnProperty</code>; thus, if the
possibility exists that an object might have a property with this name, it is
necessary to use an <em>external</em> <code>hasOwnProperty</code> in order to get correct results.</p>
<pre><code>var foo = {
hasOwnProperty: function() {
return false;
},
bar: 'Here be dragons'
};
foo.hasOwnProperty('bar'); // always returns false
// Use another Object's hasOwnProperty and call it with 'this' set to foo
({}).hasOwnProperty.call(foo, 'bar'); // true
// It's also possible use the hasOwnProperty property from the Object property for this purpuse
Object.prototype.hasOwnProperty.call(obj, 'bar'); // true
</code></pre>
</div><div><h3>In Conclusion</h3>
<p>When checking for the existence of a property on a object, <code>hasOwnProperty</code> is
the <strong>only</strong> method of doing so. It is also recommended to make <code>hasOwnProperty</code>
part of <strong>every</strong> <a href="#object.forinloop"><code>for in</code> loop</a>; this will avoid errors from
extended native <a href="#object.prototype">prototypes</a>.</p></div></article><article id="object.forinloop"><h2>The <code>for in</code> Loop</h2><div><p>Just like the <code>in</code> operator, the <code>for in</code> loop also traverses the prototype
chain when iterating over the properties of an object.</p>
<aside>
<p><strong>Note:</strong> The <code>for in</code> loop will <strong>not</strong> iterate over any properties that
have their <code>enumerable</code> attribute set to <code>false</code>; for example, the <code>length</code>
property of an array.</p>
</aside>
<pre><code>// Poisoning Object.prototype
Object.prototype.bar = 1;
var foo = {moo: 2};
for(var i in foo) {
console.log(i); // prints both bar and moo
}
</code></pre>
<p>Since it is not possible to change the behavior of the <code>for in</code> loop itself, it
is necessary to filter out the unwanted properties inside the loop body;
this is done by using the <a href="#object.hasownproperty"><code>hasOwnProperty</code></a> method of
<code>Object.prototype</code>.</p>
<aside>
<p><strong>Note:</strong> Since the <code>for in</code> always traverses the complete prototype chain, it
will get slower with each additional layer of inheritance added to an object.</p>
</aside>
</div><div><h3>Using <code>hasOwnProperty</code> for Filtering</h3>
<pre><code>// still the foo from above
for(var i in foo) {
if (foo.hasOwnProperty(i)) {
console.log(i);
}
}
</code></pre>
<p>This version is the only correct one to use. Due to the use of <code>hasOwnProperty</code>, it
will <strong>only</strong> print out <code>moo</code>. When <code>hasOwnProperty</code> is left out, the code is
prone to errors in cases where the native prototypes - e.g. <code>Object.prototype</code> -
have been extended.</p>
<p>One widely used framework which does this is <a href="http://www.prototypejs.org/">Prototype</a>. When this
framework is included, <code>for in</code> loops that do not use <code>hasOwnProperty</code> are
guaranteed to break.</p>
</div><div><h3>In Conclusion</h3>
<p>It is recommended to <strong>always</strong> use <code>hasOwnProperty</code>. Never should any
assumptions be made about the environment the code is running in, or whether the
native prototypes have been extended or not.</p></div></article></section><section id="function"><!-- Introduction--><header id="function.intro"><h1>Functions</h1></header><!-- Articles--><article id="function.general"><h2>Function Declarations and Expressions</h2><div><p>Functions in JavaScript are first class objects. That means they can be
passed around like any other value. One common use of this feature is to pass
an <em>anonymous function</em> as a callback to another, possibly asynchronous function.</p>
</div><div><h3>The <code>function</code> Declaration</h3>
<pre><code>function foo() {}
</code></pre>
<p>The above function gets <a href="#function.scopes">hoisted</a> before the execution of the
program starts; thus, it is available <em>everywhere</em> in the scope it was <em>defined</em>
in, even if called before the actual definition in the source.</p>
<pre><code>foo(); // Works because foo was created before this code runs
function foo() {}
</code></pre>
</div><div><h3>The <code>function</code> Expression</h3>
<pre><code>var foo = function() {};
</code></pre>
<p>This example assigns the unnamed and <em>anonymous</em> function to the variable <code>foo</code>. </p>
<pre><code>foo; // 'undefined'
foo(); // this raises a TypeError
var foo = function() {};
</code></pre>
<p>Due to the fact that <code>var</code> is a declaration that hoists the variable name <code>foo</code>
before the actual execution of the code starts, <code>foo</code> is already defined when
the script gets executed.</p>
<p>But since assignments only happen at runtime, the value of <code>foo</code> will default
to <a href="#core.undefined">undefined</a> before the corresponding code is executed.</p>
</div><div><h3>Named Function Expression</h3>
<p>Another special case is the assignment of named functions.</p>
<pre><code>var foo = function bar() {
bar(); // Works
}
bar(); // ReferenceError
</code></pre>
<p>Here, <code>bar</code> is not available in the outer scope, since the function only gets
assigned to <code>foo</code>; however, inside of <code>bar</code>, it is available. This is due to
how <a href="#function.scopes">name resolution</a> in JavaScript works, the name of the
function is <em>always</em> made available in the local scope of the function itself.</p></div></article><article id="function.this"><h2>How <code>this</code> Works</h2><div><p>JavaScript has a different concept of what the special name <code>this</code> refers to
than most other programming languages do. There are exactly <strong>five</strong> different
ways in which the value of <code>this</code> can be bound in the language.</p>
</div><div><h3>The Global Scope</h3>
<pre><code>this;
</code></pre>
<p>When using <code>this</code> in global scope, it will simply refer to the <em>global</em> object.</p>
</div><div><h3>Calling a Function</h3>
<pre><code>foo();
</code></pre>
<p>Here, <code>this</code> will again refer to the <em>global</em> object.</p>
<aside class="es5"><p><strong>ES5 Note:</strong> In strict mode, the global case <strong>no longer</strong> exists.
<code>this</code> will instead have the value of <code>undefined</code> in that case.</p>
</aside>
</div><div><h3>Calling a Method</h3>
<pre><code>test.foo();
</code></pre>
<p>In this example, <code>this</code> will refer to <code>test</code>.</p>
</div><div><h3>Calling a Constructor</h3>
<pre><code>new foo();
</code></pre>
<p>A function call that is preceded by the <code>new</code> keyword acts as
a <a href="#function.constructors">constructor</a>. Inside the function, <code>this</code> will refer
to a <em>newly created</em> <code>Object</code>.</p>
</div><div><h3>Explicit Setting of <code>this</code></h3>
<pre><code>function foo(a, b, c) {}
var bar = {};
foo.apply(bar, [1, 2, 3]); // array will expand to the below
foo.call(bar, 1, 2, 3); // results in a = 1, b = 2, c = 3
</code></pre>
<p>When using the <code>call</code> or <code>apply</code> methods of <code>Function.prototype</code>, the value of
<code>this</code> inside the called function gets <strong>explicitly set</strong> to the first argument
of the corresponding function call.</p>
<p>As a result, in the above example the <em>method case</em> does <strong>not</strong> apply, and <code>this</code>
inside of <code>foo</code> will be set to <code>bar</code>.</p>
<aside>
<p><strong>Note:</strong> <code>this</code> <strong>cannot</strong> be used to refer to the object inside of an <code>Object</code>
literal. So <code>var obj = {me: this}</code> will <strong>not</strong> result in <code>me</code> referring to
<code>obj</code>, since <code>this</code> only gets bound by one of the five listed cases.</p>
</aside>
</div><div><h3>Common Pitfalls</h3>
<p>While most of these cases make sense, the first one is to be considered another
mis-design of the language because it <strong>never</strong> has any practical use.</p>
<pre><code>Foo.method = function() {
function test() {
// this is set to the global object
}
test();
}
</code></pre>
<p>A common misconception is that <code>this</code> inside of <code>test</code> refers to <code>Foo</code>; while in
fact, it <strong>does not</strong>.</p>
<p>In order to gain access to <code>Foo</code> from within <code>test</code>, it is necessary to create a
local variable inside of <code>method</code> which refers to <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> is just a normal variable name, but it is commonly used for the reference to an
outer <code>this</code>. In combination with <a href="#function.closures">closures</a>, it can also
be used to pass <code>this</code> values around.</p>
</div><div><h3>Assigning Methods</h3>
<p>Another thing that does <strong>not</strong> work in JavaScript is function aliasing, which is
<strong>assigning</strong> a method to a variable.</p>
<pre><code>var test = someObject.methodTest;
test();
</code></pre>
<p>Due to the first case, <code>test</code> now acts like a plain function call; therefore,
<code>this</code> inside it will no longer refer to <code>someObject</code>.</p>
<p>While the late binding of <code>this</code> might seem like a bad idea at first, in
fact, it is what makes <a href="#object.prototype">prototypal inheritance</a> work. </p>
<pre><code>function Foo() {}
Foo.prototype.method = function() {};
function Bar() {}
Bar.prototype = Foo.prototype;
new Bar().method();
</code></pre>
<p>When <code>method</code> gets called on a instance of <code>Bar</code>, <code>this</code> will now refer to that
very instance. </p></div></article><article id="function.closures"><h2>Closures and References</h2><div><p>One of JavaScript's most powerful features is the availability of <em>closures</em>.
With closures, scopes <strong>always</strong> keep access to the outer scope, in which they
were defined. Since the only scoping that JavaScript has is
<a href="#function.scopes">function scope</a>, all functions, by default, act as closures.</p>
</div><div><h3>Emulating private variables</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>Here, <code>Counter</code> returns <strong>two</strong> closures: the function <code>increment</code> as well as
the function <code>get</code>. Both of these functions keep a <strong>reference</strong> to the scope of
<code>Counter</code> and, therefore, always keep access to the <code>count</code> variable that was
defined in that very scope.</p>
</div><div><h3>Why Private Variables Work</h3>
<p>Since it is not possible to reference or assign scopes in JavaScript, there is
<strong>no</strong> way of accessing the variable <code>count</code> from the outside. The only way to
interact with it is via the two closures.</p>
<pre><code>var foo = new Counter(4);
foo.hack = function() {
count = 1337;
};
</code></pre>
<p>The above code will <strong>not</strong> change the variable <code>count</code> in the scope of <code>Counter</code>,
since <code>foo.hack</code> was not defined in <strong>that</strong> scope. It will instead create - or
override - the <em>global</em> variable <code>count</code>.</p>
</div><div><h3>Closures Inside Loops</h3>
<p>One often made mistake is to use closures inside of loops, as if they were
copying the value of the loops index variable.</p>
<pre><code>for(var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
</code></pre>
<p>The above will <strong>not</strong> output the numbers <code>0</code> through <code>9</code>, but will simply print
the number <code>10</code> ten times.</p>
<p>The <em>anonymous</em> function keeps a <strong>reference</strong> to <code>i</code>. At the time
<code>console.log</code> gets called, the <code>for loop</code> has already finished, and the value of
<code>i</code> as been set to <code>10</code>.</p>
<p>In order to get the desired behavior, it is necessary to create a <strong>copy</strong> of
the value of <code>i</code>.</p>
</div><div><h3>Avoiding the Reference Problem</h3>
<p>In order to copy the value of the loop's index variable, it is best to use an
<a href="#function.scopes">anonymous wrapper</a>.</p>
<pre><code>for(var i = 0; i < 10; i++) {
(function(e) {
setTimeout(function() {
console.log(e);
}, 1000);
})(i);
}
</code></pre>
<p>The anonymous outer function gets called immediately with <code>i</code> as its first
argument and will receive a copy of the <strong>value</strong> of <code>i</code> as its parameter <code>e</code>.</p>
<p>The anonymous function that gets passed to <code>setTimeout</code> now has a reference to
<code>e</code>, whose value does <strong>not</strong> get changed by the loop.</p>
<p>There is another possible way of achieving this, which is to return a function
from the anonymous wrapper that will then have the same behavior as the code
above.</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>The <code>arguments</code> Object</h2><div><p>Every function scope in JavaScript can access the special variable <code>arguments</code>.
This variable holds a list of all the arguments that were passed to the function.</p>
<aside>
<p><strong>Note:</strong> In case <code>arguments</code> has already been defined inside the function's
scope either via a <code>var</code> statement or being the name of a formal parameter,
the <code>arguments</code> object will not be created.</p>
</aside>
<p>The <code>arguments</code> object is <strong>not</strong> an <code>Array</code>. While it has some of the
semantics of an array - namely the <code>length</code> property - it does not inherit from
<code>Array.prototype</code> and is in fact an <code>Object</code>.</p>
<p>Due to this, it is <strong>not</strong> possible to use standard array methods like <code>push</code>,
<code>pop</code> or <code>slice</code> on <code>arguments</code>. While iteration with a plain <code>for</code> loop works
just fine, it is necessary to convert it to a real <code>Array</code> in order to use the
standard <code>Array</code> methods on it.</p>
</div><div><h3>Converting to an Array</h3>
<p>The code below will return a new <code>Array</code> containing all the elements of the
<code>arguments</code> object.</p>
<pre><code>Array.prototype.slice.call(arguments);
</code></pre>
<p>Because this conversion is <strong>slow</strong>, it is <strong>not recommended</strong> to use it in
performance-critical sections of code.</p>
</div><div><h3>Passing Arguments</h3>
<p>The following is the recommended way of passing arguments from one function to
another.</p>
<pre><code>function foo() {
bar.apply(null, arguments);
}
function bar(a, b, c) {
// do stuff here
}
</code></pre>
<p>Another trick is to use both <code>call</code> and <code>apply</code> together to create fast, unbound
wrappers.</p>
<pre><code>function Foo() {}
Foo.prototype.method = function(a, b, c) {
console.log(this, a, b, c);
};
// Create an unbound version of "method"
// It takes the parameters: this, arg1, arg2...argN
Foo.method = function() {
// Result: Foo.prototype.method.call(this, arg1, arg2... argN)
Function.call.apply(Foo.prototype.method, arguments);
};
</code></pre>
</div><div><h3>Formal Parameters and Arguments Indices</h3>
<p>The <code>arguments</code> object creates <em>getter</em> and <em>setter</em> functions for both its
properties, as well as the function's formal parameters.</p>
<p>As a result, changing the value of a formal parameter will also change the value
of the corresponding property on the <code>arguments</code> object, and the other way around.</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>Performance Myths and Truths</h3>
<p>The <code>arguments</code> object is always created with the only two exceptions being the
cases where it is declared as a name inside of a function or one of its formal
parameters. It does not matter whether it is used or not.</p>
<p>Both <em>getters</em> and <em>setters</em> are <strong>always</strong> created; thus, using it has nearly
no performance impact at all, especially not in real world code where there is
more than a simple access to the <code>arguments</code> object's properties.</p>
<aside class="es5"><p><strong>ES5 Note:</strong> These <em>getters</em> and <em>setters</em> are not created in strict mode.</p>
</aside>
<p>However, there is one case which will drastically reduce the performance in
modern JavaScript engines. That case is the use of <code>arguments.callee</code>.</p>
<pre><code>function foo() {
arguments.callee; // do something with this function object
arguments.callee.caller; // and the calling function object
}
function bigLoop() {
for(var i = 0; i < 100000; i++) {
foo(); // Would normally be inlined...
}
}
</code></pre>
<p>In the above code, <code>foo</code> can no longer be a subject to <a href="http://en.wikipedia.org/wiki/Inlining">inlining</a> since it
needs to know about both itself and its caller. This not only defeats possible
performance gains that would arise from inlining, but it also breaks encapsulation
because the function may now be dependent on a specific calling context.</p>
<p>It is <strong>highly recommended</strong> to <strong>never</strong> make use of <code>arguments.callee</code> or any of
its properties.</p>
<aside class="es5"><p><strong>ES5 Note:</strong> In strict mode, <code>arguments.callee</code> will throw a <code>TypeError</code> since
its use has been deprecated.</p>
</aside></div></article><article id="function.constructors"><h2>Constructors</h2><div><p>Constructors in JavaScript are yet again different from many other languages. Any
function call that is preceded by the <code>new</code> keyword acts as a constructor.</p>
<p>Inside the constructor - the called function - the value of <code>this</code> refers to a
newly created object. The <a href="#object.prototype">prototype</a> of this <strong>new</strong>
object is set to the <code>prototype</code> of the function object that was invoked as the
constructor.</p>
<p>If the function that was called has no explicit <code>return</code> statement, then it
implicitly returns the value of <code>this</code> - the new object. </p>
<pre><code>function Foo() {
this.bla = 1;
}
Foo.prototype.test = function() {
console.log(this.bla);
};
var test = new Foo();
</code></pre>
<p>The above calls <code>Foo</code> as constructor and sets the <code>prototype</code> of the newly
created object to <code>Foo.prototype</code>.</p>
<p>In case of an explicit <code>return</code> statement, the function returns the value
specified that statement, <strong>but only</strong> if the return value is an <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>When the <code>new</code> keyword is omitted, the function will <strong>not</strong> return a new object. </p>
<pre><code>function Foo() {
this.bla = 1; // gets set on the global object
}
Foo(); // undefined
</code></pre>
<p>While the above example might still appear to work in some cases, due to the
workings of <a href="#function.this"><code>this</code></a> in JavaScript, it will use the
<em>global object</em> as the value of <code>this</code>.</p>
</div><div><h3>Factories</h3>
<p>In order to be able to omit the <code>new</code> keyword, the constructor function has to
explicitly return a value.</p>
<pre><code>function Bar() {
var value = 1;
return {
method: function() {
return value;
}
}
}
Bar.prototype = {
foo: function() {}
};
new Bar();
Bar();
</code></pre>
<p>Both calls to <code>Bar</code> return the exact same thing, a newly create object which
has a property called <code>method</code> on it, which is a
<a href="#function.closures">Closure</a>.</p>
<p>It is also to note that the call <code>new Bar()</code> does <strong>not</strong> affect the prototype
of the returned object. While the prototype will be set on the newly created
object, <code>Bar</code> never returns that new object.</p>
<p>In the above example, there is no functional difference between using and
not using the <code>new</code> keyword.</p>
</div><div><h3>Creating New Objects via Factories</h3>
<p>An often made recommendation is to <strong>not</strong> use <code>new</code> because forgetting its use
may lead to bugs.</p>
<p>In order to create new object, one should rather use a factory and construct a
new object inside of that factory.</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>While the above is robust against a missing <code>new</code> keyword and certainly makes
the use of <a href="#function.closures">private variables</a> easier, it comes with some
downsides.</p>
<ol>
<li>It uses more memory since the created objects do <strong>not</strong> share the methods
on a prototype.</li>
<li>In order to inherit the factory needs to copy all the methods from another
object or put that object on the prototype of the new object.</li>
<li>Dropping the prototype chain just because of a left out <code>new</code> keyword
somehow goes against the spirit of the language.</li>
</ol>
</div><div><h3>In Conclusion</h3>
<p>While omitting the <code>new</code> keyword might lead to bugs, it is certainly <strong>not</strong> a
reason to drop the use of prototypes altogether. In the end it comes down to
which solution is better suited for the needs of the application, it is
especially important to choose a specific style of object creation <strong>and stick</strong>
with it.</p></div></article><article id="function.scopes"><h2>Scopes and Namespaces</h2><div><p>Although JavaScript deals fine with the syntax of two matching curly
braces for blocks, it does <strong>not</strong> support block scope; hence, all that is left
in the language is <em>function scope</em>.</p>
<pre><code>function test() { // a scope
for(var i = 0; i < 10; i++) { // not a scope
// count
}
console.log(i); // 10
}
</code></pre>
<aside>
<p><strong>Note:</strong> When not used in an assignment, return statement or as a function
argument, the <code>{...}</code> notation will get interpreted as a block statement and
<strong>not</strong> as an object literal. This, in conjunction with
<a href="#core.semicolon">automatic insertion of semicolons</a>, can lead to subtle errors.</p>
</aside>
<p>There are also no distinct namespaces in JavaScript, which means that everything
gets defined in one <em>globally shared</em> namespace.</p>
<p>Each time a variable is referenced, JavaScript will traverse upwards through all
the scopes until it finds it. In the case that it reaches the global scope and
still has not found the requested name, it will raise a <code>ReferenceError</code>.</p>
</div><div><h3>The Bane of Global Variables</h3>
<pre><code>// script A
foo = '42';
// script B
var foo = '42'
</code></pre>
<p>The above two scripts do <strong>not</strong> have the same effect. Script A defines a
variable called <code>foo</code> in the <em>global</em> scope, and script B defines a <code>foo</code> in the
<em>current</em> scope.</p>
<p>Again, that is <strong>not</strong> at all the <em>same effect</em>: not using <code>var</code> can have major
implications.</p>
<pre><code>// global scope
var foo = 42;
function test() {
// local scope
foo = 21;
}
test();
foo; // 21
</code></pre>
<p>Leaving out the <code>var</code> statement inside the function <code>test</code> will override the
value of <code>foo</code>. While this might not seem like a big deal at first, having
thousands of lines of JavaScript and not using <code>var</code> will introduce horrible,
hard-to-track-down bugs.</p>
<pre><code>// global scope
var items = [/* some list */];
for(var i = 0; i < 10; i++) {
subLoop();
}
function subLoop() {
// scope of subLoop
for(i = 0; i < 10; i++) { // missing var statement
// do amazing stuff!
}
}
</code></pre>
<p>The outer loop will terminate after the first call to <code>subLoop</code>, since <code>subLoop</code>
overwrites the global value of <code>i</code>. Using a <code>var</code> for the second <code>for</code> loop would
have easily avoided this error. The <code>var</code> statement should <strong>never</strong> be left out
unless the <em>desired effect</em> is to affect the outer scope.</p>
</div><div><h3>Local Variables</h3>
<p>The only source for local variables in JavaScript are
<a href="#function.general">function</a> parameters and variables that were declared via the
<code>var</code> statement.</p>
<pre><code>// global scope
var foo = 1;
var bar = 2;
var i = 2;
function test(i) {
// local scope of the function test
i = 5;
var foo = 3;
bar = 4;
}
test(10);
</code></pre>
<p>While <code>foo</code> and <code>i</code> are local variables inside the scope of the function <code>test</code>,
the assignment of <code>bar</code> will override the global variable with the same name.</p>
</div><div><h3>Hoisting</h3>
<p>JavaScript <strong>hoists</strong> declarations. This means that both <code>var</code> statements and
<code>function</code> declarations will be moved to the top of their enclosing scope.</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>The above code gets transformed before any execution is started. JavaScript moves
the <code>var</code> statements, as well as the <code>function</code> declarations to the top of the
nearest surrounding scope.</p>
<pre><code>// var statements got moved here