forked from google/styleguide
-
Notifications
You must be signed in to change notification settings - Fork 2
/
javascriptguide.xml
3627 lines (3256 loc) · 132 KB
/
javascriptguide.xml
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
<?xml version = '1.0'?>
<?xml-stylesheet type="text/xsl" href="styleguide.xsl"?>
<GUIDE title="Google JavaScript Style Guide">
<p class="revision">
Revision 2.93
</p>
<address>
Aaron Whyte<br/>
Bob Jervis<br/>
Dan Pupius<br/>
Erik Arvidsson<br/>
Fritz Schneider<br/>
Robby Walker<br/>
</address>
<OVERVIEW>
<CATEGORY title="Important Note">
<STYLEPOINT title="Displaying Hidden Details in this Guide">
<SUMMARY>
This style guide contains many details that are initially
hidden from view. They are marked by the triangle icon, which you
see here on your left. Click it now.
You should see "Hooray" appear below.
</SUMMARY>
<BODY>
<p>
Hooray! Now you know you can expand points to get more
details. Alternatively, there's a "toggle all" at the
top of this document.
</p>
</BODY>
</STYLEPOINT>
</CATEGORY>
<CATEGORY title="Background">
<p>
JavaScript is the main client-side scripting language used
by many of Google's open-source
projects.
This style guide is a list of <em>do</em>s and <em>don't</em>s for
JavaScript programs.
</p>
</CATEGORY>
</OVERVIEW>
<CATEGORY title="JavaScript Language Rules">
<STYLEPOINT title="var">
<SUMMARY>
Declarations with <code>var</code>: Always
</SUMMARY>
<BODY>
<DECISION>
When you fail to specify <code>var</code>,
the variable gets placed in the global context, potentially clobbering
existing values. Also, if there's no declaration, it's hard to tell in
what scope a variable lives (e.g., it could be in the Document or
Window just as easily as in the local scope). So always declare with
<code>var</code>.
</DECISION>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Constants">
<SUMMARY>
<ul>
<li>Use <code>NAMES_LIKE_THIS</code> for constant <em>values</em>.</li>
<li>Use <code>@const</code> to indicate a constant (non-overwritable)
<em>pointer</em> (a variable or property).</li>
<li>Never use the
<a href="https://developer.mozilla.org/en/JavaScript/Reference/Statements/const">
<code>const</code> keyword</a>
as it's not supported in Internet Explorer.</li>
</ul>
</SUMMARY>
<BODY>
<DECISION>
<SUBSECTION title="Constant values">
<p>If a value is intended to be <em>constant</em>
and <em>immutable</em>, it should be given a name
in <code>CONSTANT_VALUE_CASE</code>.
<code>ALL_CAPS</code> additionally implies <code>@const</code>
(that the value is not overwritable).
</p>
<p>Primitive types (<code>number</code>, <code>string</code>,
<code>boolean</code>) are constant values.</p>
<p><code>Objects</code>'
immutability is more subjective — objects should be
considered immutable only if they do not demonstrate observable
state change. This is not enforced by the compiler.</p>
</SUBSECTION>
<SUBSECTION title="Constant pointers (variables and properties)">
<p>The <code>@const</code> annotation on a variable or property
implies that it is not overwritable. This is enforced by the
compiler at build time. This behavior is consistent with the
<a href="https://developer.mozilla.org/en/JavaScript/Reference/Statements/const">
<code>const</code> keyword</a> (which we do not use due to the
lack of support in Internet Explorer).</p>
<p>A <code>@const</code> annotation on a method additionally
implies that the method cannot not be overridden in subclasses.
</p>
<p>A <code>@const</code> annotation on a constructor implies the
class cannot be subclassed (akin to <code>final</code> in Java).
</p>
</SUBSECTION>
<SUBSECTION title="Examples">
<p>Note that <code>@const</code> does not necessarily imply
<code>CONSTANT_VALUES_CASE</code>.
However, <code>CONSTANT_VALUES_CASE</code>
<em>does</em> imply <code>@const</code>.
</p>
<CODE_SNIPPET>
/**
* Request timeout in milliseconds.
* @type {number}
*/
goog.example.TIMEOUT_IN_MILLISECONDS = 60;
</CODE_SNIPPET>
<p>The number of seconds in a minute never changes. It is a
constant value. <code>ALL_CAPS</code>
also implies <code>@const</code>, so the constant cannot be
overwritten.
</p>
<p>The open source compiler will allow the symbol to be
overwritten because the constant is
<em>not</em> marked as <code>@const</code>.</p>
<CODE_SNIPPET>
/**
* Map of URL to response string.
* @const
*/
MyClass.fetchedUrlCache_ = new goog.structs.Map();
</CODE_SNIPPET>
<CODE_SNIPPET>
/**
* Class that cannot be subclassed.
* @const
* @constructor
*/
sloth.MyFinalClass = function() {};
</CODE_SNIPPET>
<p>In this case, the pointer can never be overwritten, but
value is highly mutable and <b>not</b> constant (and thus in
<code>camelCase</code>, not <code>ALL_CAPS</code>).</p>
</SUBSECTION>
</DECISION>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Semicolons">
<SUMMARY>
Always use semicolons.
</SUMMARY>
<BODY>
<p>Relying on implicit insertion can cause subtle, hard to debug
problems. Don't do it. You're better than that.</p>
<p>There are a couple places where missing semicolons are particularly
dangerous:</p>
<BAD_CODE_SNIPPET>
// 1.
MyClass.prototype.myMethod = function() {
return 42;
} // No semicolon here.
(function() {
// Some initialization code wrapped in a function to create a scope for locals.
})();
var x = {
'i': 1,
'j': 2
} // No semicolon here.
// 2. Trying to do one thing on Internet Explorer and another on Firefox.
// I know you'd never write code like this, but throw me a bone.
[ffVersion, ieVersion][isIE]();
var THINGS_TO_EAT = [apples, oysters, sprayOnCheese] // No semicolon here.
// 3. conditional execution a la bash
-1 == resultOfOperation() || die();
</BAD_CODE_SNIPPET>
<SUBSECTION title="So what happens?">
<ol>
<li>JavaScript error - first the function returning 42 is called
with the second function as a parameter, then the number 42 is
"called" resulting in an error.</li>
<li>You will most likely get a 'no such property in undefined'
error at runtime as it tries to call
<code>x[ffVersion, ieVersion][isIE]()</code>.</li>
<li><code>die</code> is always called since the array minus 1 is
<code>NaN</code> which is never equal to anything (not even if
<code>resultOfOperation()</code> returns <code>NaN</code>) and
<code>THINGS_TO_EAT</code> gets assigned the result of
<code>die()</code>.</li>
</ol>
</SUBSECTION>
<SUBSECTION title="Why?">
<p>JavaScript requires statements to end with a semicolon, except when
it thinks it can safely infer their existence. In each of these
examples, a function declaration or object or array literal is used
inside a statement. The closing brackets are not enough to signal
the end of the statement. Javascript never ends a statement if the
next token is an infix or bracket operator.</p>
<p>This has really surprised people, so make sure your assignments end
with semicolons.</p>
</SUBSECTION>
<SUBSECTION title="Clarification: Semicolons and functions">
<p>Semicolons should be included at the end of function expressions,
but not at the end of function declarations. The distinction is
best illustrated with an example:</p>
<CODE_SNIPPET>
var foo = function() {
return true;
}; // semicolon here.
function foo() {
return true;
} // no semicolon here.
</CODE_SNIPPET>
</SUBSECTION>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Nested functions">
<SUMMARY>Yes</SUMMARY>
<BODY>
<p>Nested functions can be very useful, for example in the creation of
continuations and for the task of hiding helper functions. Feel free
to use them.</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Function Declarations Within Blocks">
<SUMMARY>No</SUMMARY>
<BODY>
<p>Do not do this:</p>
<BAD_CODE_SNIPPET>
if (x) {
function foo() {}
}
</BAD_CODE_SNIPPET>
<p>While most script engines support Function Declarations within blocks
it is not part of ECMAScript (see
<a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm">ECMA-262</a>,
clause 13 and 14). Worse implementations are inconsistent with each
other and with future EcmaScript proposals. ECMAScript only allows for
Function Declarations in the root statement list of a script or
function. Instead use a variable initialized with a Function
Expression to define a function within a block:</p>
<CODE_SNIPPET>
if (x) {
var foo = function() {};
}
</CODE_SNIPPET>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Exceptions">
<SUMMARY>Yes</SUMMARY>
<BODY>
<p>You basically can't avoid exceptions if you're doing something
non-trivial (using an application development framework, etc.).
Go for it.</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Custom exceptions">
<SUMMARY>Yes</SUMMARY>
<BODY>
<p>Without custom exceptions, returning error information from a
function that also returns a value can be tricky, not to mention
inelegant. Bad solutions include passing in a reference type to hold
error information or always returning Objects with a potential
error member. These basically amount to a primitive exception
handling hack. Feel free to use custom exceptions when
appropriate.</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Standards features">
<SUMMARY>Always preferred over non-standards features</SUMMARY>
<BODY>
<p>For maximum portability and compatibility, always prefer standards
features over non-standards features (e.g.,
<code>string.charAt(3)</code> over <code>string[3]</code> and element
access with DOM functions instead of using an application-specific
shorthand).</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Wrapper objects for primitive types">
<SUMMARY>No</SUMMARY>
<BODY>
<p>There's no reason to use wrapper objects for primitive types, plus
they're dangerous:</p>
<BAD_CODE_SNIPPET>
var x = new Boolean(false);
if (x) {
alert('hi'); // Shows 'hi'.
}
</BAD_CODE_SNIPPET>
<p>Don't do it!</p>
<p>However type casting is fine.</p>
<CODE_SNIPPET>
var x = Boolean(0);
if (x) {
alert('hi'); // This will never be alerted.
}
typeof Boolean(0) == 'boolean';
typeof new Boolean(0) == 'object';
</CODE_SNIPPET>
<p>This is very useful for casting things to
<code>number</code>, <code>string</code> and <code>boolean</code>.</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Multi-level prototype hierarchies">
<SUMMARY>Not preferred</SUMMARY>
<BODY>
<p>Multi-level prototype hierarchies are how JavaScript implements
inheritance. You have a multi-level hierarchy if you have a
user-defined class D with another user-defined class B as its
prototype. These hierarchies are much harder to get right than they
first appear! </p>
<p>For that reason, it is best to use <code>goog.inherits()</code> from
<a href="http://code.google.com/closure/library/">
the Closure Library
</a>
or a similar library function.
</p>
<CODE_SNIPPET>
function D() {
goog.base(this)
}
goog.inherits(D, B);
D.prototype.method = function() {
...
};
</CODE_SNIPPET>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Method and property definitions">
<SUMMARY><code>/** @constructor */
function SomeConstructor() {
this.someProperty = 1;
}
Foo.prototype.someMethod = function() { ... };</code></SUMMARY>
<BODY>
<p>While there are several ways to attach methods and properties to an
object created via "new", the preferred style for methods
is:</p>
<CODE_SNIPPET>
Foo.prototype.bar = function() {
/* ... */
};
</CODE_SNIPPET>
<p>The preferred style for other properties is to initialize the field
in the constructor:</p>
<CODE_SNIPPET>
/** @constructor */
function Foo() {
this.bar = value;
}
</CODE_SNIPPET>
<SUBSECTION title="Why?">
<p>Current JavaScript engines optimize based on the "shape"
of an object, <a href="https://developers.google.com/v8/design#prop_access">
adding a property to an object (including overriding
a value set on the prototype) changes the shape and can degrade
performance.</a></p>
</SUBSECTION>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="delete">
<SUMMARY>Prefer <code>this.foo = null</code>.</SUMMARY>
<BODY>
<CODE_SNIPPET>
Foo.prototype.dispose = function() {
this.property_ = null;
};
</CODE_SNIPPET>
<p>Instead of:</p>
<BAD_CODE_SNIPPET>
Foo.prototype.dispose = function() {
delete this.property_;
};
</BAD_CODE_SNIPPET>
<p>In modern JavaScript engines, changing the number of properties on an
object is much slower than reassigning the values. The delete keyword
should be avoided except when it is necessary to remove a property
from an object's iterated list of keys, or to change the result of
<code>if (key in obj)</code>.</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Closures">
<SUMMARY>Yes, but be careful.</SUMMARY>
<BODY>
<p>The ability to create closures is perhaps the most useful and often
overlooked feature of JS. Here is
<a href="http://jibbering.com/faq/faq_notes/closures.html">
a good description of how closures work</a>.</p>
<p>One thing to keep in mind, however, is that a closure keeps a pointer
to its enclosing scope. As a result, attaching a closure to a DOM
element can create a circular reference and thus, a memory leak. For
example, in the following code:</p>
<BAD_CODE_SNIPPET>
function foo(element, a, b) {
element.onclick = function() { /* uses a and b */ };
}
</BAD_CODE_SNIPPET>
<p>the function closure keeps a reference to <code>element</code>,
<code>a</code>, and <code>b</code> even if it never uses
<code>element</code>. Since <code>element</code> also keeps a
reference to the closure, we have a cycle that won't be cleaned up by
garbage collection. In these situations, the code can be structured
as follows:</p>
<CODE_SNIPPET>
function foo(element, a, b) {
element.onclick = bar(a, b);
}
function bar(a, b) {
return function() { /* uses a and b */ };
}
</CODE_SNIPPET>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="eval()">
<SUMMARY>
Only for code loaders and REPL (Read–eval–print loop)
</SUMMARY>
<BODY>
<p><code>eval()</code> makes for confusing semantics and is dangerous
to use if the string being <code>eval()</code>'d contains user input.
There's usually a better, clearer, and safer way to write your code,
so its use is generally not permitted.</p>
<p>For RPC you can always use JSON and read the result using
<code>JSON.parse()</code> instead of <code>eval()</code>.</p>
<p>Let's assume we have a server that returns something like this:</p>
<CODE_SNIPPET>
{
"name": "Alice",
"id": 31502,
"email": "[email protected]"
}
</CODE_SNIPPET>
<BAD_CODE_SNIPPET>
var userInfo = eval(feed);
var email = userInfo['email'];
</BAD_CODE_SNIPPET>
<p>If the feed was modified to include malicious JavaScript code, then
if we use <code>eval</code> then that code will be executed.</p>
<CODE_SNIPPET>
var userInfo = JSON.parse(feed);
var email = userInfo['email'];
</CODE_SNIPPET>
<p>With <code>JSON.parse</code>, invalid JSON (including all executable
JavaScript) will cause an exception to be thrown.</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="with() {}">
<SUMMARY>No</SUMMARY>
<BODY>
<p>Using <code>with</code> clouds the semantics of your program.
Because the object of the <code>with</code> can have properties that
collide with local variables, it can drastically change the meaning
of your program. For example, what does this do?</p>
<BAD_CODE_SNIPPET>
with (foo) {
var x = 3;
return x;
}
</BAD_CODE_SNIPPET>
<p>Answer: anything. The local variable <code>x</code> could be
clobbered by a property of <code>foo</code> and perhaps it even has
a setter, in which case assigning <code>3</code> could cause lots of
other code to execute. Don't use <code>with</code>.</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="this">
<SUMMARY>
Only in object constructors, methods, and in setting up closures
</SUMMARY>
<BODY>
<p>The semantics of <code>this</code> can be tricky. At times it refers
to the global object (in most places), the scope of the caller (in
<code>eval</code>), a node in the DOM tree (when attached using an
event handler HTML attribute), a newly created object (in a
constructor), or some other object (if function was
<code>call()</code>ed or <code>apply()</code>ed).</p>
<p>Because this is so easy to get wrong, limit its use to those places
where it is required:</p>
<ul>
<li>in constructors</li>
<li>in methods of objects (including in the creation of closures)</li>
</ul>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="for-in loop">
<SUMMARY>
Only for iterating over keys in an object/map/hash
</SUMMARY>
<BODY>
<p><code>for-in</code> loops are often incorrectly used to loop over
the elements in an <code>Array</code>. This is however very error
prone because it does not loop from <code>0</code> to
<code>length - 1</code> but over all the present keys in the object
and its prototype chain. Here are a few cases where it fails:</p>
<BAD_CODE_SNIPPET>
function printArray(arr) {
for (var key in arr) {
print(arr[key]);
}
}
printArray([0,1,2,3]); // This works.
var a = new Array(10);
printArray(a); // This is wrong.
a = document.getElementsByTagName('*');
printArray(a); // This is wrong.
a = [0,1,2,3];
a.buhu = 'wine';
printArray(a); // This is wrong again.
a = new Array;
a[3] = 3;
printArray(a); // This is wrong again.
</BAD_CODE_SNIPPET>
<p>Always use normal for loops when using arrays.</p>
<CODE_SNIPPET>
function printArray(arr) {
var l = arr.length;
for (var i = 0; i < l; i++) {
print(arr[i]);
}
}
</CODE_SNIPPET>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Associative Arrays">
<SUMMARY>
Never use <code>Array</code> as a map/hash/associative array
</SUMMARY>
<BODY>
<p>Associative <code>Array</code>s are not allowed... or more precisely
you are not allowed to use non number indexes for arrays. If you need
a map/hash use <code>Object</code> instead of <code>Array</code> in
these cases because the features that you want are actually features
of <code>Object</code> and not of <code>Array</code>.
<code>Array</code> just happens to extend <code>Object</code> (like
any other object in JS and therefore you might as well have used
<code>Date</code>, <code>RegExp</code> or <code>String</code>).</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Multiline string literals">
<SUMMARY>No</SUMMARY>
<BODY>
<p>Do not do this:</p>
<BAD_CODE_SNIPPET>
var myString = 'A rather long string of English text, an error message \
actually that just keeps going and going -- an error \
message to make the Energizer bunny blush (right through \
those Schwarzenegger shades)! Where was I? Oh yes, \
you\'ve got an error and all the extraneous whitespace is \
just gravy. Have a nice day.';
</BAD_CODE_SNIPPET>
<p>The whitespace at the beginning of each line can't be safely stripped
at compile time; whitespace after the slash will result in tricky
errors; and while most script engines support this, it is not part
of ECMAScript. </p>
<p>Use string concatenation instead:</p>
<CODE_SNIPPET>
var myString = 'A rather long string of English text, an error message ' +
'actually that just keeps going and going -- an error ' +
'message to make the Energizer bunny blush (right through ' +
'those Schwarzenegger shades)! Where was I? Oh yes, ' +
'you\'ve got an error and all the extraneous whitespace is ' +
'just gravy. Have a nice day.';
</CODE_SNIPPET>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Array and Object literals">
<SUMMARY>Yes</SUMMARY>
<BODY>
<p>Use <code>Array</code> and <code>Object</code> literals instead of
<code>Array</code> and <code>Object</code> constructors.</p>
<p>Array constructors are error-prone due to their arguments.</p>
<BAD_CODE_SNIPPET>
// Length is 3.
var a1 = new Array(x1, x2, x3);
// Length is 2.
var a2 = new Array(x1, x2);
// If x1 is a number and it is a natural number the length will be x1.
// If x1 is a number but not a natural number this will throw an exception.
// Otherwise the array will have one element with x1 as its value.
var a3 = new Array(x1);
// Length is 0.
var a4 = new Array();
</BAD_CODE_SNIPPET>
<p>Because of this, if someone changes the code to pass 1 argument
instead of 2 arguments, the array might not have the expected
length.</p>
<p>To avoid these kinds of weird cases, always use the more readable
array literal.</p>
<CODE_SNIPPET>
var a = [x1, x2, x3];
var a2 = [x1, x2];
var a3 = [x1];
var a4 = [];
</CODE_SNIPPET>
<p>Object constructors don't have the same problems, but for readability
and consistency object literals should be used.</p>
<BAD_CODE_SNIPPET>
var o = new Object();
var o2 = new Object();
o2.a = 0;
o2.b = 1;
o2.c = 2;
o2['strange key'] = 3;
</BAD_CODE_SNIPPET>
<p>Should be written as:</p>
<CODE_SNIPPET>
var o = {};
var o2 = {
a: 0,
b: 1,
c: 2,
'strange key': 3
};
</CODE_SNIPPET>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Modifying prototypes of builtin objects">
<SUMMARY>No</SUMMARY>
<BODY>
<p>Modifying builtins like <code>Object.prototype</code> and
<code>Array.prototype</code> are strictly forbidden. Modifying other
builtins like <code>Function.prototype</code> is less dangerous but
still leads to hard to debug issues in production and should be
avoided.</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Internet Explorer's Conditional Comments">
<SUMMARY>No</SUMMARY>
<BODY>
<p>Don't do this:</p>
<BAD_CODE_SNIPPET>
var f = function () {
/*@cc_on if (@_jscript) { return 2* @*/ 3; /*@ } @*/
};
</BAD_CODE_SNIPPET>
<p>Conditional Comments hinder automated tools as they can vary the
JavaScript syntax tree at runtime.</p>
</BODY>
</STYLEPOINT>
</CATEGORY>
<CATEGORY title="JavaScript Style Rules">
<STYLEPOINT title="Naming">
<SUMMARY>
<p>In general, use
<code>functionNamesLikeThis</code>,
<code>variableNamesLikeThis</code>,
<code>ClassNamesLikeThis</code>,
<code>EnumNamesLikeThis</code>,
<code>methodNamesLikeThis</code>,
<code>CONSTANT_VALUES_LIKE_THIS</code>,
<code>foo.namespaceNamesLikeThis.bar</code>, and
<code>filenameslikethis.js</code>.
</p>
</SUMMARY>
<BODY>
<SUBSECTION title="Properties and methods">
<ul>
<li><em>Private</em> properties and methods should be named with a
trailing underscore.
</li>
<li><em>Protected</em> properties and methods should be
named without a trailing underscore (like public ones).</li>
</ul>
<p>For more information on <em>private</em> and <em>protected</em>,
read the section on
<a href="#Visibility__private_and_protected_fields_">
visibility</a>.
</p>
</SUBSECTION>
<SUBSECTION title="Method and function parameter">
<p>Optional function arguments start with <code>opt_</code>.</p>
<p>Functions that take a variable number of arguments should have the
last argument named <code>var_args</code>. You may not refer to
<code>var_args</code> in the code; use the <code>arguments</code>
array.</p>
<p>Optional and variable arguments can also be specified in
<code>@param</code> annotations. Although either convention is
acceptable to the compiler, using both together is preferred.</p>
</SUBSECTION>
<SUBSECTION title="Getters and Setters">
<p>EcmaScript 5 getters and setters for properties are discouraged.
However, if they are used, then getters must not change observable
state.</p>
<BAD_CODE_SNIPPET>
/**
* WRONG -- Do NOT do this.
*/
var foo = { get next() { return this.nextId++; } };
</BAD_CODE_SNIPPET>
</SUBSECTION>
<SUBSECTION title="Accessor functions">
<p>Getters and setters methods for properties are not required.
However, if they are used, then getters must be named
<code>getFoo()</code> and setters must be named
<code>setFoo(value)</code>. (For boolean getters,
<code>isFoo()</code> is also acceptable, and often sounds more
natural.)</p>
</SUBSECTION>
<SUBSECTION title="Namespaces">
<p>JavaScript has no inherent packaging or namespacing support.</p>
<p>Global name conflicts are difficult to debug, and can cause
intractable problems when two projects try to integrate. In order
to make it possible to share common JavaScript code, we've adopted
conventions to prevent collisions. </p>
<SUBSUBSECTION title="Use namespaces for global code">
<p><em>ALWAYS</em> prefix identifiers in the global scope with a
unique pseudo namespace related to the project or library. If you
are working on "Project Sloth", a reasonable pseudo namespace
would be <code>sloth.*</code>.</p>
<CODE_SNIPPET>
var sloth = {};
sloth.sleep = function() {
...
};
</CODE_SNIPPET>
<p>Many JavaScript libraries, including
<a href="http://code.google.com/closure/library/">
the Closure Library
</a>
and
<a href="http://www.dojotoolkit.org/">
Dojo toolkit
</a>
give you high-level functions for declaring your namespaces.
Be consistent about how you declare your namespaces.</p>
<CODE_SNIPPET>
goog.provide('sloth');
sloth.sleep = function() {
...
};
</CODE_SNIPPET>
</SUBSUBSECTION>
<SUBSUBSECTION title="Respect namespace ownership">
<p>When choosing a child-namespace, make sure that the owners of the
parent namespace know what you are doing. If you start a project
that creates hats for sloths, make sure that the Sloth team knows
that you're using <code>sloth.hats</code>.</p>
</SUBSUBSECTION>
<SUBSUBSECTION title="Use different namespaces for external code and internal code">
<p>"External code" is code that comes from outside your codebase,
and is compiled independently. Internal and external names should
be kept strictly separate. If you're using an external library
that makes things available in <code>foo.hats.*</code>, your
internal code should not define all its symbols in
<code>foo.hats.*</code>, because it will break if the other
team defines new symbols.</p>
<BAD_CODE_SNIPPET>
foo.require('foo.hats');
/**
* WRONG -- Do NOT do this.
* @constructor
* @extends {foo.hats.RoundHat}
*/
foo.hats.BowlerHat = function() {
};
</BAD_CODE_SNIPPET>
<p>If you need to define new APIs on an external namespace, then you
should explicitly export the public API functions, and only those
functions. Your internal code should call the internal APIs by
their internal names, for consistency and so that the compiler
can optimize them better.</p>
<CODE_SNIPPET>
foo.provide('googleyhats.BowlerHat');
foo.require('foo.hats');
/**
* @constructor
* @extends {foo.hats.RoundHat}
*/
googleyhats.BowlerHat = function() {
...
};
goog.exportSymbol('foo.hats.BowlerHat', googleyhats.BowlerHat);
</CODE_SNIPPET>
</SUBSUBSECTION>
<SUBSUBSECTION title="Alias long type names to improve readability">
<p>Use local aliases for fully-qualified types if doing so improves
readability. The name of a local alias should match the last part
of the type.</p>
<CODE_SNIPPET>
/**
* @constructor
*/
some.long.namespace.MyClass = function() {
};
/**
* @param {some.long.namespace.MyClass} a
*/
some.long.namespace.MyClass.staticHelper = function(a) {
...
};
myapp.main = function() {
var MyClass = some.long.namespace.MyClass;
var staticHelper = some.long.namespace.MyClass.staticHelper;
staticHelper(new MyClass());
};
</CODE_SNIPPET>
<p>Do not create local aliases of namespaces. Namespaces should only
be aliased using <a href="#goog-scope">goog.scope</a>.</p>
<BAD_CODE_SNIPPET>
myapp.main = function() {
var namespace = some.long.namespace;
namespace.MyClass.staticHelper(new namespace.MyClass());
};
</BAD_CODE_SNIPPET>
<p>Avoid accessing properties of an aliased type, unless it is an
enum.</p>
<CODE_SNIPPET>
/** @enum {string} */
some.long.namespace.Fruit = {
APPLE: 'a',
BANANA: 'b'
};
myapp.main = function() {
var Fruit = some.long.namespace.Fruit;
switch (fruit) {
case Fruit.APPLE:
...
case Fruit.BANANA:
...
}
};
</CODE_SNIPPET>
<BAD_CODE_SNIPPET>
myapp.main = function() {
var MyClass = some.long.namespace.MyClass;
MyClass.staticHelper(null);
};
</BAD_CODE_SNIPPET>
<p>Never create aliases in the global scope. Use them only in
function blocks.</p>
</SUBSUBSECTION>
</SUBSECTION>
<SUBSECTION title="Filenames">
<p>Filenames should be all lowercase in order to avoid confusion on
case-sensitive platforms. Filenames should end in <code>.js</code>,
and should contain no punctuation except for <code>-</code> or
<code>_</code> (prefer <code>-</code> to <code>_</code>).</p>
</SUBSECTION>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Custom toString() methods">
<SUMMARY>
Must always succeed without side effects.
</SUMMARY>
<BODY>
<p>You can control how your objects string-ify themselves by defining a
custom <code>toString()</code> method. This is fine, but you need
to ensure that your method (1) always succeeds and (2) does not have
side-effects. If your method doesn't meet these criteria, it's very
easy to run into serious problems. For example, if
<code>toString()</code> calls a method that does an
<code>assert</code>, <code>assert</code> might try to output the name
of the object in which it failed, which of course requires calling
<code>toString()</code>.</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Deferred initialization">
<SUMMARY>OK</SUMMARY>
<BODY>
<p>It isn't always possible to initialize variables at the point of
declaration, so deferred initialization is fine.</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Explicit scope">
<SUMMARY>Always</SUMMARY>
<BODY>
<p>Always use explicit scope - doing so increases portability and
clarity. For example, don't rely on <code>window</code> being in the
scope chain. You might want to use your function in another
application for which <code>window</code> is not the content
window.</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Code formatting">
<SUMMARY>Expand for more information.</SUMMARY>
<BODY>
<p>We follow the <a href="cppguide.html#Formatting">C++ formatting
rules</a> in spirit, with the following additional clarifications.</p>
<SUBSECTION title="Curly Braces">
<p>Because of implicit semicolon insertion, always start your curly
braces on the same line as whatever they're opening. For
example:</p>
<CODE_SNIPPET>
if (something) {
// ...
} else {
// ...
}
</CODE_SNIPPET>
</SUBSECTION>
<SUBSECTION title="Array and Object Initializers">
<p>Single-line array and object initializers are allowed when they
fit on a line:</p>
<CODE_SNIPPET>