diff --git a/README.md b/README.md index d5525cb9f1..9871693f94 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,13 @@ -# Airbnb JavaScript Style Guide() { +# JavaScript Style Guide() { *A mostly reasonable approach to JavaScript* ## Table of Contents - + 1. [General Coding Principles](#general-coding-principles) 1. [Types](#types) 1. [Objects](#objects) + 1. [OOP](#oop) 1. [Arrays](#arrays) 1. [Strings](#strings) 1. [Functions](#functions) @@ -29,28 +30,52 @@ 1. [Testing](#testing) 1. [Performance](#performance) 1. [Resources](#resources) - 1. [In the Wild](#in-the-wild) - 1. [Translation](#translation) - 1. [The JavaScript Style Guide Guide](#guide-guide) - 1. [Contributors](#contributors) 1. [License](#license) + + + +## General Coding Principles + + - 99% of code should be housed in external javascript files. They should be included at the END of the BODY tag for maximum page performance. + + - Don't rely on the user-agent string. Do proper feature detection. (More at [Dive Into HTML5: Detection](http://diveintohtml5.info/detect.html) & [jQuery.support docs](http://api.jquery.com/jQuery.support/)) + + - Don't use `document.write()`. + + - 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. + + - Comment your code! It helps reduce time spent troubleshooting JavaScript functions. + + - Organize your code as an [Object Literal/Singleton](http://kaijaeger.com/articles/the-singleton-design-pattern-in-javascript.html), in the [Module Pattern](http://www.yuiblog.com/blog/2007/06/12/module-pattern/), or as an [Object with constructors](http://mckoss.com/jscript/object.htm). + + - Minimize global variables - the less globals you create, the better. Generally one, for your application namespace, is a good number: + + ```javascript + window.globalVar = { ... } + ``` + + - 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). + + - 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. + + **[[⬆]](#TOC)** + + ## Types - **Primitives**: When you access a primitive type you work directly on its value - + `string` - + `number` - + `boolean` - + `null` - + `undefined` + * `string` + * `number` + * `boolean` + * `null` + * `undefined` ```javascript var foo = 1, bar = foo; - bar = 9; - console.log(foo, bar); // => 1, 9 ``` - **Complex**: When you access a complex type you work on a reference to its value @@ -68,7 +93,24 @@ console.log(foo[0], bar[0]); // => 9, 9 ``` - **[[⬆]](#TOC)** + - Type Checks + + + **String:** `typeof object === "string"` + + **Number:** `typeof object === "number"` + + **Boolean:** `typeof object === "boolean"` + + **Object:** `typeof object === "object"` + + **Plain Object:** `jQuery.isPlainObject(object)` + + **Function:** `jQuery.isFunction(object)` + + **Array:** `jQuery.isArray(object)` + + **Element:** `object.nodeType` + + **null:** `object === null` + + **null or undefined:** `object == null` + + **undefined:** + + **Global Variables:** `typeof variable === "undefined"` + + **Local Variables:** `variable === undefined` + + **Properties:** `object.prop === undefined` + + **[[⬆]](#TOC)** ## Objects @@ -101,6 +143,55 @@ ``` **[[⬆]](#TOC)** +## OOP + + - Definition order + + ```javascript + var object = function () { + //private variables + //public variables + //private functions + //public functions + } + ``` + - Method and property definitions: + + ```javascript + /** @constructor */ + function SomeConstructor() { + this.someProperty = 1; + } + Foo.prototype.someMethod = function() { ... }; + ``` + + While there are several ways to attach methods and properties to an object created via `new`, the preferred style for methods is: + + ```javascript + Foo.prototype.bar = function() { + /* ... */ + }; + ``` + + The preferred style for other properties is to initialize the field in the constructor: + + ```javascript + /** @constructor */ + function Foo() { + this.bar = value; + } + ``` + + - Modifying prototypes of builtin objects: + 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. + + - Custom toString() methods + Must always succeed without side effects. + + 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()`. + + **[[⬆]](#TOC)** + ## Arrays - Use the literal syntax for array creation @@ -113,7 +204,7 @@ var items = []; ``` - - If you don't know array length use Array#push. + - If you don't know array length use `Array#push`. ```javascript var someStack = []; @@ -126,7 +217,7 @@ someStack.push('abracadabra'); ``` - - When you need to copy an array use Array#slice. [jsPerf](http://jsperf.com/converting-arguments-to-an-array/7) + - When you need to copy an array use `Array#slice`. [jsPerf](http://jsperf.com/converting-arguments-to-an-array/7) ```javascript var len = items.length, @@ -163,8 +254,7 @@ var fullName = 'Bob ' + this.lastName; ``` - - Strings longer than 80 characters should be written across multiple lines using string concatenation. - - Note: If overused, long strings with concatenation could impact performance. [jsPerf](http://jsperf.com/ya-string-concat) & [Discussion](https://github.com/airbnb/javascript/issues/40) + - Strings longer than 80 characters should be written across multiple lines using string concatenation. **Note**: If overused, long strings with concatenation could impact performance. [jsPerf](http://jsperf.com/ya-string-concat) & [Discussion](https://github.com/airbnb/javascript/issues/40) ```javascript // bad @@ -188,7 +278,7 @@ 'fast.'; ``` - - When programatically building up a string, use Array#join instead of string concatenation. Mostly for IE: [jsPerf](http://jsperf.com/string-vs-array-concat/2). + - When programatically building up a string, use `Array#join` instead of string concatenation. Mostly for IE: [jsPerf](http://jsperf.com/string-vs-array-concat/2). ```javascript var items, @@ -209,7 +299,7 @@ length = messages.length; // bad - function inbox(messages) { + function inbox (messages) { items = '