Skip to content

Commit 2ddbc79

Browse files
author
Dmitry Vasyuta
committed
Merge with Google
1 parent 8b94609 commit 2ddbc79

File tree

1 file changed

+151
-23
lines changed

1 file changed

+151
-23
lines changed

README.md

Lines changed: 151 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
1. [General Coding Principles](#general-coding-principles)
88
1. [Types](#types)
99
1. [Objects](#objects)
10+
1. [OOP](#oop)
1011
1. [Arrays](#arrays)
1112
1. [Strings](#strings)
1213
1. [Functions](#functions)
@@ -46,47 +47,40 @@
4647

4748
- Don't use document.write().
4849

49-
- Definition order
50-
51-
```javascript
52-
var object = function () {
53-
//private variables
54-
//public variables
55-
//private functions
56-
//public functions
57-
}
58-
```
59-
6050
- Strive to create functions which can be generalized, take parameters, and return values. This allows for substantial code reuse and, when combined with includes or external scripts, can reduce the overhead when scripts need to change. For example, instead of hard coding a pop-window with window size, options, and url, consider creating a function which takes size, url, and options as variables.
6151

6252
- Comment your code! It helps reduce time spent troubleshooting JavaScript functions.
6353

6454
- Organize your code as an Object Literal/Singleton, in the Module Pattern, or as an Object with constructors.
6555

66-
- Minimize global variables - the less globals you create, the better. Generally one, for your application namespace, is a good number.
56+
- Minimize global variables - the less globals you create, the better. Generally one, for your application namespace, is a good number:
6757

6858
```javascript
6959
window.globalVar = { ... }
7060
```
7161

72-
**[[⬆]](#TOC)**
62+
- For maximum portability and compatibility, always prefer standards features over non-standards features (e.g., `string.charAt(3)` over `string[3] ` and element access with DOM functions instead of using an application-specific shorthand).
63+
64+
- Explicit scope
65+
Always use explicit scope - doing so increases portability and clarity. For example, don't rely on window being in the scope chain. You might want to use your function in another application for which window is not the content window.
66+
67+
**[[⬆]](#TOC)**
68+
7369
7470
## <a name='types'>Types</a>
7571
7672
- **Primitives**: When you access a primitive type you work directly on its value
7773
78-
+ `string`
79-
+ `number`
80-
+ `boolean`
81-
+ `null`
82-
+ `undefined`
74+
* `string`
75+
* `number`
76+
* `boolean`
77+
* `null`
78+
* `undefined`
8379
8480
```javascript
8581
var foo = 1,
8682
bar = foo;
87-
8883
bar = 9;
89-
9084
console.log(foo, bar); // => 1, 9
9185
```
9286
- **Complex**: When you access a complex type you work on a reference to its value
@@ -121,7 +115,7 @@
121115
+ **Local Variables:** `variable === undefined`
122116
+ **Properties:** `object.prop === undefined`
123117
124-
**[[⬆]](#TOC)**
118+
**[[⬆]](#TOC)**
125119
126120
## <a name='objects'>Objects</a>
127121
@@ -154,6 +148,55 @@
154148
```
155149
**[[⬆]](#TOC)**
156150

151+
## <a name='oop'>OOP</a>
152+
153+
- Definition order
154+
155+
```javascript
156+
var object = function () {
157+
//private variables
158+
//public variables
159+
//private functions
160+
//public functions
161+
}
162+
```
163+
- Method and property definitions:
164+
165+
```javascript
166+
/** @constructor */
167+
function SomeConstructor() {
168+
this.someProperty = 1;
169+
}
170+
Foo.prototype.someMethod = function() { ... };
171+
```
172+
173+
While there are several ways to attach methods and properties to an object created via "new", the preferred style for methods is:
174+
175+
```javascript
176+
Foo.prototype.bar = function() {
177+
/* ... */
178+
};
179+
```
180+
181+
The preferred style for other properties is to initialize the field in the constructor:
182+
183+
```javascript
184+
/** @constructor */
185+
function Foo() {
186+
this.bar = value;
187+
}
188+
```
189+
190+
- Modifying prototypes of builtin objects:
191+
Modifying builtins like `Object.prototype` and `Array.prototype` are strictly forbidden. Modifying other builtins like `Function.prototype` is less dangerous but still leads to hard to debug issues in production and should be avoided.
192+
193+
- Custom toString() methods
194+
Must always succeed without side effects.
195+
196+
You can control how your objects string-ify themselves by defining a custom `toString()` 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 `toString()` calls a method that does an assert, assert might try to output the name of the object in which it failed, which of course requires calling `toString()`.
197+
198+
**[[⬆]](#TOC)**
199+
157200
## <a name='arrays'>Arrays</a>
158201
159202
- Use the literal syntax for array creation
@@ -1184,6 +1227,47 @@
11841227
};
11851228
```
11861229
1230+
- Constant values
1231+
1232+
If a value is intended to be constant and immutable, it should be given a name in `CONSTANT_VALUE_CASE`. `ALL_CAPS` additionally implies @const (that the value is not overwritable).
1233+
1234+
Primitive types (number, string, boolean) are constant values.
1235+
1236+
Objects' immutabilty is more subjective — objects should be considered immutable only if they do not demonstrate obeserverable state change. This is not enforced by the compiler.
1237+
1238+
- Constant pointers (variables and properties)
1239+
1240+
The @const 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 const keyword (which we do not use due to the lack of support in Internet Explorer).
1241+
1242+
A @const annotation on a method additionally implies that the method should not be overriden in subclasses.
1243+
1244+
**Examples**
1245+
1246+
Note that @const does not necessarily imply `CONSTANT_VALUES_CASE`. However, `CONSTANT_VALUES_CASE` does imply @const.
1247+
1248+
```javascript
1249+
/**
1250+
* Request timeout in milliseconds.
1251+
* @type {number}
1252+
*/
1253+
goog.example.TIMEOUT_IN_MILLISECONDS = 60;
1254+
```
1255+
1256+
The number of seconds in a minute never changes. It is a constant value. `ALL_CAPS` also implies @const, so the constant cannot be overwritten.
1257+
1258+
The open source compiler will allow the symbol it to be overwritten because the constant is not marked as @const.
1259+
1260+
```javascript
1261+
/**
1262+
* Map of URL to response string.
1263+
* @const
1264+
*/
1265+
MyClass.fetchedUrlCache_ = new goog.structs.Map();
1266+
```
1267+
1268+
In this case, the pointer can never be overwritten, but value is highly mutable and not constant (and thus in `camelCase`, not `ALL_CAPS`).
1269+
1270+
11871271
**[[⬆]](#TOC)**
11881272
11891273
@@ -1419,7 +1503,7 @@
14191503
$($sidebar[0]).find('ul');
14201504
```
14211505
1422-
**[[⬆]](#TOC)**
1506+
**[[⬆]](#TOC)**
14231507
14241508
14251509
## <a name='es5'>ECMAScript 5 Compatibility</a>
@@ -1439,11 +1523,55 @@
14391523
}
14401524
```
14411525
1442-
**[[⬆]](#TOC)**
1526+
**[[⬆]](#TOC)**
14431527
14441528
14451529
## <a name='performance'>Performance</a>
14461530
1531+
- Prefer `this.foo = null`.
1532+
1533+
```javascript
1534+
Foo.prototype.dispose = function() {
1535+
this.property_ = null;
1536+
};
1537+
```
1538+
1539+
Instead of:
1540+
1541+
```javascript
1542+
Foo.prototype.dispose = function() {
1543+
delete this.property_;
1544+
};
1545+
```
1546+
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 `if (key in obj)`.
1547+
1548+
1549+
- Closures
1550+
1551+
Yes, but be careful.
1552+
The ability to create closures is perhaps the most useful and often overlooked feature of JS. Here is a good description of how closures work .
1553+
1554+
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:
1555+
1556+
```javascript
1557+
function foo(element, a, b) {
1558+
element.onclick = function() { /* uses a and b */ };
1559+
}
1560+
```
1561+
1562+
the function closure keeps a reference to element, a, and b even if it never uses element. Since element 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:
1563+
1564+
```javascript
1565+
function foo(element, a, b) {
1566+
element.onclick = bar(a, b);
1567+
}
1568+
1569+
function bar(a, b) {
1570+
return function() { /* uses a and b */ }
1571+
}
1572+
```
1573+
1574+
* * *
14471575
- [On Layout & Web Performance](http://kellegous.com/j/2013/01/26/layout-performance/)
14481576
- [String vs Array Concat](http://jsperf.com/string-vs-array-concat/2)
14491577
- [Try/Catch Cost In a Loop](http://jsperf.com/try-catch-in-loop-cost)

0 commit comments

Comments
 (0)