diff --git a/README.md b/README.md
index 02ecc75ee6..5c1913cc55 100644
--- a/README.md
+++ b/README.md
@@ -4,14 +4,21 @@
*A mostly reasonable approach to JavaScript*
+[For our old ES5-only guide click here](es5/).
## Table of Contents
1. [Types](#types)
+ 1. [References](#references)
1. [Objects](#objects)
1. [Arrays](#arrays)
+ 1. [Destructuring](#destructuring)
1. [Strings](#strings)
1. [Functions](#functions)
+ 1. [Arrow Functions](#arrow-functions)
+ 1. [Constructors](#constructors)
+ 1. [Modules](#modules)
+ 1. [Iterators and Generators](#iterators-and-generators)
1. [Properties](#properties)
1. [Variables](#variables)
1. [Hoisting](#hoisting)
@@ -24,11 +31,10 @@
1. [Type Casting & Coercion](#type-casting--coercion)
1. [Naming Conventions](#naming-conventions)
1. [Accessors](#accessors)
- 1. [Constructors](#constructors)
1. [Events](#events)
- 1. [Modules](#modules)
1. [jQuery](#jquery)
1. [ECMAScript 5 Compatibility](#ecmascript-5-compatibility)
+ 1. [ECMAScript 6 Styles](#ecmascript-6-styles)
1. [Testing](#testing)
1. [Performance](#performance)
1. [Resources](#resources)
@@ -50,8 +56,8 @@
+ `undefined`
```javascript
- var foo = 1;
- var bar = foo;
+ const foo = 1;
+ let bar = foo;
bar = 9;
@@ -64,8 +70,8 @@
+ `function`
```javascript
- var foo = [1, 2];
- var bar = foo;
+ const foo = [1, 2];
+ const bar = foo;
bar[0] = 9;
@@ -74,29 +80,77 @@
**[⬆ back to top](#table-of-contents)**
+## References
+
+ - Use `const` for all of your references; avoid using `var`.
+
+ > Why? This ensures that you can't reassign your references (mutation), which can lead to bugs and difficult to comprehend code.
+
+ ```javascript
+ // bad
+ var a = 1;
+ var b = 2;
+
+ // good
+ const a = 1;
+ const b = 2;
+ ```
+
+ - If you must mutate references, use `let` instead of `var`.
+
+ > Why? `let` is block-scoped rather than function-scoped like `var`.
+
+ ```javascript
+ // bad
+ var count = 1;
+ if (true) {
+ count += 1;
+ }
+
+ // good, use the let.
+ let count = 1;
+ if (true) {
+ count += 1;
+ }
+ ```
+
+ - Note that both `let` and `const` are block-scoped.
+
+ ```javascript
+ // const and let only exist in the blocks they are defined in.
+ {
+ let a = 1;
+ const b = 1;
+ }
+ console.log(a); // ReferenceError
+ console.log(b); // ReferenceError
+ ```
+
+**[⬆ back to top](#table-of-contents)**
+
## Objects
- Use the literal syntax for object creation.
```javascript
// bad
- var item = new Object();
+ const item = new Object();
// good
- var item = {};
+ const item = {};
```
- Don't use [reserved words](http://es5.github.io/#x7.6.1) as keys. It won't work in IE8. [More info](https://github.com/airbnb/javascript/issues/61).
```javascript
// bad
- var superman = {
+ const superman = {
default: { clark: 'kent' },
private: true
};
// good
- var superman = {
+ const superman = {
defaults: { clark: 'kent' },
hidden: true
};
@@ -106,21 +160,118 @@
```javascript
// bad
- var superman = {
+ const superman = {
class: 'alien'
};
// bad
- var superman = {
+ const superman = {
klass: 'alien'
};
// good
- var superman = {
+ const superman = {
type: 'alien'
};
```
+
+ - Use computed property names when creating objects with dynamic property names.
+
+ > Why? They allow you to define all the properties of an object in one place.
+
+ ```javascript
+
+ function getKey(k) {
+ return `a key named ${k}`;
+ }
+
+ // bad
+ const obj = {
+ id: 5,
+ name: 'San Francisco'
+ };
+ obj[getKey('enabled')] = true;
+
+ // good
+ const obj = {
+ id: 5,
+ name: 'San Francisco',
+ [getKey('enabled')]: true
+ };
+ ```
+
+
+ - Use object method shorthand.
+
+ ```javascript
+ // bad
+ const atom = {
+ value: 1,
+
+ addValue: function (value) {
+ return atom.value + value;
+ }
+ };
+
+ // good
+ const atom = {
+ value: 1,
+
+ addValue(value) {
+ return atom.value + value;
+ }
+ };
+ ```
+
+
+ - Use property value shorthand.
+
+ > Why? It is shorter to write and descriptive.
+
+ ```javascript
+ const lukeSkywalker = 'Luke Skywalker';
+
+ // bad
+ const obj = {
+ lukeSkywalker: lukeSkywalker
+ };
+
+ // good
+ const obj = {
+ lukeSkywalker
+ };
+ ```
+
+ - Group your shorthand properties at the beginning of your object declaration.
+
+ > Why? It's easier to tell which properties are using the shorthand.
+
+ ```javascript
+ const anakinSkywalker = 'Anakin Skywalker';
+ const lukeSkywalker = 'Luke Skywalker';
+
+ // bad
+ const obj = {
+ episodeOne: 1,
+ twoJedisWalkIntoACantina: 2,
+ lukeSkywalker,
+ episodeThree: 3,
+ mayTheFourth: 4,
+ anakinSkywalker
+ };
+
+ // good
+ const obj = {
+ lukeSkywalker,
+ anakinSkywalker,
+ episodeOne: 1,
+ twoJedisWalkIntoACantina: 2,
+ episodeThree: 3,
+ mayTheFourth: 4
+ };
+ ```
+
**[⬆ back to top](#table-of-contents)**
## Arrays
@@ -129,16 +280,16 @@
```javascript
// bad
- var items = new Array();
+ const items = new Array();
// good
- var items = [];
+ const items = [];
```
- Use Array#push instead of direct assignment to add items to an array.
```javascript
- var someStack = [];
+ const someStack = [];
// bad
@@ -148,50 +299,108 @@
someStack.push('abracadabra');
```
- - When you need to copy an array use Array#slice. [jsPerf](http://jsperf.com/converting-arguments-to-an-array/7)
+
+ - Use array spreads `...` to copy arrays.
```javascript
- var len = items.length;
- var itemsCopy = [];
- var i;
-
// bad
+ const len = items.length;
+ const itemsCopy = [];
+ let i;
+
for (i = 0; i < len; i++) {
itemsCopy[i] = items[i];
}
// good
- itemsCopy = items.slice();
+ const itemsCopy = [...items];
+ ```
+ - To convert an array-like object to an array, use Array#from.
+
+ ```javascript
+ const foo = document.querySelectorAll('.foo');
+ const nodes = Array.from(foo);
```
- - To convert an array-like object to an array, use Array#slice.
+**[⬆ back to top](#table-of-contents)**
+
+## Destructuring
+
+ - Use object destructuring when accessing and using multiple properties of an object.
+
+ > Why? Destructuring saves you from creating temporary references for those properties.
```javascript
- function trigger() {
- var args = Array.prototype.slice.call(arguments);
- ...
+ // bad
+ function getFullName(user) {
+ const firstName = user.firstName;
+ const lastName = user.lastName;
+
+ return `${firstName} ${lastName}`;
+ }
+
+ // good
+ function getFullName(obj) {
+ const { firstName, lastName } = obj;
+ return `${firstName} ${lastName}`;
+ }
+
+ // best
+ function getFullName({ firstName, lastName }) {
+ return `${firstName} ${lastName}`;
}
```
-**[⬆ back to top](#table-of-contents)**
+ - Use array destructuring.
+ ```javascript
+ const arr = [1, 2, 3, 4];
-## Strings
+ // bad
+ const first = arr[0];
+ const second = arr[1];
- - Use single quotes `''` for strings.
+ // good
+ const [first, second] = arr;
+ ```
+
+ - Use object destructuring for multiple return values, not array destructuring.
+
+ > Why? You can add new properties over time or change the order of things without breaking call sites.
```javascript
// bad
- var name = "Bob Parr";
+ function processInput(input) {
+ // then a miracle occurs
+ return [left, right, top, bottom];
+ }
+
+ // the caller needs to think about the order of return data
+ const [left, __, top] = processInput(input);
// good
- var name = 'Bob Parr';
+ function processInput(input) {
+ // then a miracle occurs
+ return { left, right, top, bottom };
+ }
+
+ // the caller selects only the data they need
+ const { left, right } = processInput(input);
+ ```
+
+
+**[⬆ back to top](#table-of-contents)**
+## Strings
+
+ - Use single quotes `''` for strings.
+
+ ```javascript
// bad
- var fullName = "Bob " + this.lastName;
+ const name = "Bob Parr";
// good
- var fullName = 'Bob ' + this.lastName;
+ const name = 'Bob Parr';
```
- Strings longer than 80 characters should be written across multiple lines using string concatenation.
@@ -199,62 +408,39 @@
```javascript
// bad
- var errorMessage = 'This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.';
+ const errorMessage = 'This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.';
// bad
- var errorMessage = 'This is a super long error that was thrown because \
+ const errorMessage = 'This is a super long error that was thrown because \
of Batman. When you stop to think about how Batman had anything to do \
with this, you would get nowhere \
fast.';
// good
- var errorMessage = 'This is a super long error that was thrown because ' +
+ const errorMessage = 'This is a super long error that was thrown because ' +
'of Batman. When you stop to think about how Batman had anything to do ' +
'with this, you would get nowhere fast.';
```
- - When programmatically 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;
- var messages;
- var length;
- var i;
-
- messages = [{
- state: 'success',
- message: 'This one worked.'
- }, {
- state: 'success',
- message: 'This one worked as well.'
- }, {
- state: 'error',
- message: 'This one did not work.'
- }];
+
+ - When programmatically building up strings, use template strings instead of concatenation.
- length = messages.length;
+ > Why? Template strings give you a readable, concise syntax with proper newlines and string interpolation features.
+ ```javascript
// bad
- function inbox(messages) {
- items = '
';
-
- for (i = 0; i < length; i++) {
- items += '- ' + messages[i].message + '
';
- }
+ function sayHi(name) {
+ return 'How are you, ' + name + '?';
+ }
- return items + '
';
+ // bad
+ function sayHi(name) {
+ return ['How are you, ', name, '?'].join();
}
// good
- function inbox(messages) {
- items = [];
-
- for (i = 0; i < length; i++) {
- // use direct assignment in this case because we're micro-optimizing.
- items[i] = '' + messages[i].message + '';
- }
-
- return '';
+ function sayHi(name) {
+ return `How are you, ${name}?`;
}
```
@@ -263,21 +449,25 @@
## Functions
- - Function expressions:
+ - Use function declarations instead of function expressions.
+
+ > Why? Function declarations are named, so they're easier to identify in call stacks. Also, the whole body of a function declaration is hoisted, whereas only the reference of a function expression is hoisted. This rule makes it possible to always use [Arrow Functions](#arrow-functions) in place of function expressions.
```javascript
- // anonymous function expression
- var anonymous = function() {
- return true;
+ // bad
+ const foo = function () {
};
- // named function expression
- var named = function named() {
- return true;
- };
+ // good
+ function foo() {
+ }
+ ```
+
+ - Function expressions:
+ ```javascript
// immediately-invoked function expression (IIFE)
- (function() {
+ (() => {
console.log('Welcome to the Internet. Please follow me.');
})();
```
@@ -294,9 +484,9 @@
}
// good
- var test;
+ let test;
if (currentUser) {
- test = function test() {
+ test = () => {
console.log('Yup.');
};
}
@@ -316,8 +506,314 @@
}
```
+
+ - Never use `arguments`, opt to use rest syntax `...` instead.
+
+ > Why? `...` is explicit about which arguments you want pulled. Plus rest arguments are a real Array and not Array-like like `arguments`.
+
+ ```javascript
+ // bad
+ function concatenateAll() {
+ const args = Array.prototype.slice.call(arguments);
+ return args.join('');
+ }
+
+ // good
+ function concatenateAll(...args) {
+ return args.join('');
+ }
+ ```
+
+
+ - Use default parameter syntax rather than mutating function arguments.
+
+ ```javascript
+ // really bad
+ function handleThings(opts) {
+ // No! We shouldn't mutate function arguments.
+ // Double bad: if opts is falsy it'll be set to an object which may
+ // be what you want but it can introduce subtle bugs.
+ opts = opts || {};
+ // ...
+ }
+
+ // still bad
+ function handleThings(opts) {
+ if (opts === void 0) {
+ opts = {};
+ }
+ // ...
+ }
+
+ // good
+ function handleThings(opts = {}) {
+ // ...
+ }
+ ```
+
+ - Avoid side effects with default parameters
+
+ > Why? They are confusing to reason about.
+
+ ```javascript
+ var b = 1;
+ // bad
+ function count(a = b++) {
+ console.log(a);
+ }
+ count(); // 1
+ count(); // 2
+ count(3); // 3
+ count(); // 3
+ ```
+
+
**[⬆ back to top](#table-of-contents)**
+## Arrow Functions
+
+ - When you must use function expressions (as when passing an anonymous function), use arrow function notation.
+
+ > Why? It creates a version of the function that executes in the context of `this`, which is usually what you want, and is a more concise syntax.
+
+ > Why not? If you have a fairly complicated function, you might move that logic out into its own function declaration.
+
+ ```javascript
+ // bad
+ [1, 2, 3].map(function (x) {
+ return x * x;
+ });
+
+ // good
+ [1, 2, 3].map((x) => {
+ return x * x
+ });
+ ```
+
+ - If the function body fits on one line, feel free to omit the braces and use implicit return. Otherwise, add the braces and use a `return` statement.
+
+ > Why? Syntactic sugar. It reads well when multiple functions are chained together.
+
+ > Why not? If you plan on returning an object.
+
+ ```javascript
+ // good
+ [1, 2, 3].map((x) => x * x);
+
+ // good
+ [1, 2, 3].map((x) => {
+ return { number: x };
+ });
+ ```
+
+ - Always use parentheses around the arguments. Omitting the parentheses makes the functions less readable and only works for single arguments.
+
+ > Why? These declarations read better with parentheses. They are also required when you have multiple parameters so this enforces consistency.
+
+ ```javascript
+ // bad
+ [1, 2, 3].map(x => x * x);
+
+ // good
+ [1, 2, 3].map((x) => x * x);
+ ```
+
+**[⬆ back to top](#table-of-contents)**
+
+
+## Constructors
+
+ - Always use `class`. Avoid manipulating `prototype` directly.
+
+ > Why? `class` syntax is more concise and easier to reason about.
+
+ ```javascript
+ // bad
+ function Queue(contents = []) {
+ this._queue = [...contents];
+ }
+ Queue.prototype.pop = function() {
+ const value = this._queue[0];
+ this._queue.splice(0, 1);
+ return value;
+ }
+
+
+ // good
+ class Queue {
+ constructor(contents = []) {
+ this._queue = [...contents];
+ }
+ pop() {
+ const value = this._queue[0];
+ this._queue.splice(0, 1);
+ return value;
+ }
+ }
+ ```
+
+ - Use `extends` for inheritance.
+
+ > Why? It is a built-in way to inherit prototype functionality without breaking `instanceof`.
+
+ ```javascript
+ // bad
+ const inherits = require('inherits');
+ function PeekableQueue(contents) {
+ Queue.apply(this, contents);
+ }
+ inherits(PeekableQueue, Queue);
+ PeekableQueue.prototype.peek = function() {
+ return this._queue[0];
+ }
+
+ // good
+ class PeekableQueue extends Queue {
+ peek() {
+ return this._queue[0];
+ }
+ }
+ ```
+
+ - Methods can return `this` to help with method chaining.
+
+ ```javascript
+ // bad
+ Jedi.prototype.jump = function() {
+ this.jumping = true;
+ return true;
+ };
+
+ Jedi.prototype.setHeight = function(height) {
+ this.height = height;
+ };
+
+ const luke = new Jedi();
+ luke.jump(); // => true
+ luke.setHeight(20); // => undefined
+
+ // good
+ class Jedi {
+ jump() {
+ this.jumping = true;
+ return this;
+ }
+
+ setHeight(height) {
+ this.height = height;
+ return this;
+ }
+ }
+
+ const luke = new Jedi();
+
+ luke.jump()
+ .setHeight(20);
+ ```
+
+
+ - It's okay to write a custom toString() method, just make sure it works successfully and causes no side effects.
+
+ ```javascript
+ class Jedi {
+ contructor(options = {}) {
+ this.name = options.name || 'no name';
+ }
+
+ getName() {
+ return this.name;
+ }
+
+ toString() {
+ return `Jedi - ${this.getName()}`;
+ }
+ }
+ ```
+
+**[⬆ back to top](#table-of-contents)**
+
+
+## Modules
+
+ - Always use modules (`import`/`export`) over a non-standard module system. You can always transpile to your preferred module system.
+
+ > Why? Modules are the future, let's start using the future now.
+
+ ```javascript
+ // bad
+ const AirbnbStyleGuide = require('./AirbnbStyleGuide');
+ module.exports = AirbnbStyleGuide.es6;
+
+ // ok
+ import AirbnbStyleGuide from './AirbnbStyleGuide';
+ export default AirbnbStyleGuide.es6;
+
+ // best
+ import { es6 } from './AirbnbStyleGuide';
+ export default es6;
+ ```
+
+ - Do not use wildcard imports.
+
+ > Why? This makes sure you have a single default export.
+
+ ```javascript
+ // bad
+ import * as AirbnbStyleGuide from './AirbnbStyleGuide';
+
+ // good
+ import AirbnbStyleGuide from './AirbnbStyleGuide';
+ ```
+
+ - And do not export directly from an import.
+
+ > Why? Although the one-liner is concise, having one clear way to import and one clear way to export makes things consistent.
+
+ ```javascript
+ // bad
+ // filename es6.js
+ export { es6 as default } from './airbnbStyleGuide';
+
+ // good
+ // filename es6.js
+ import { es6 } from './AirbnbStyleGuide';
+ export default es6;
+ ```
+
+**[⬆ back to top](#table-of-contents)**
+
+## Iterators and Generators
+
+ - Don't use iterators. Prefer JavaScript's higher-order functions like `map()` and `reduce()` instead of loops like `for-of`.
+
+ > Why? This enforces our immutable rule. Dealing with pure functions that return values is easier to reason about than side-effects.
+
+ ```javascript
+ const numbers = [1, 2, 3, 4, 5];
+
+ // bad
+ let sum = 0;
+ for (let num of numbers) {
+ sum += num;
+ }
+
+ sum === 15;
+
+ // good
+ let sum = 0;
+ numbers.forEach((num) => sum += num);
+ sum === 15;
+
+ // best (use the functional force)
+ const sum = numbers.reduce((total, num) => total + num, 0);
+ sum === 15;
+ ```
+
+ - Don't use generators.
+
+ > Why? They don't transpile well to ES5.
+
+**[⬆ back to top](#table-of-contents)**
## Properties
@@ -325,22 +821,22 @@
- Use dot notation when accessing properties.
```javascript
- var luke = {
+ const luke = {
jedi: true,
age: 28
};
// bad
- var isJedi = luke['jedi'];
+ const isJedi = luke['jedi'];
// good
- var isJedi = luke.jedi;
+ const isJedi = luke.jedi;
```
- Use subscript notation `[]` when accessing properties with a variable.
```javascript
- var luke = {
+ const luke = {
jedi: true,
age: 28
};
@@ -349,7 +845,7 @@
return luke[prop];
}
- var isJedi = getProp('jedi');
+ const isJedi = getProp('jedi');
```
**[⬆ back to top](#table-of-contents)**
@@ -357,90 +853,77 @@
## Variables
- - Always use `var` to declare variables. Not doing so will result in global variables. We want to avoid polluting the global namespace. Captain Planet warned us of that.
+ - Always use `const` to declare variables. Not doing so will result in global variables. We want to avoid polluting the global namespace. Captain Planet warned us of that.
```javascript
// bad
superPower = new SuperPower();
// good
- var superPower = new SuperPower();
+ const superPower = new SuperPower();
```
- - Use one `var` declaration per variable.
- It's easier to add new variable declarations this way, and you never have
- to worry about swapping out a `;` for a `,` or introducing punctuation-only
- diffs.
+ - Use one `const` declaration per variable.
+
+ > Why? It's easier to add new variable declarations this way, and you never have to worry about swapping out a `;` for a `,` or introducing punctuation-only diffs.
```javascript
// bad
- var items = getItems(),
+ const items = getItems(),
goSportsTeam = true,
dragonball = 'z';
// bad
// (compare to above, and try to spot the mistake)
- var items = getItems(),
+ const items = getItems(),
goSportsTeam = true;
dragonball = 'z';
// good
- var items = getItems();
- var goSportsTeam = true;
- var dragonball = 'z';
+ const items = getItems();
+ const goSportsTeam = true;
+ const dragonball = 'z';
```
- - Declare unassigned variables last. This is helpful when later on you might need to assign a variable depending on one of the previous assigned variables.
+ - Group all your `const`s and then group all your `let`s.
+
+ > Why? This is helpful when later on you might need to assign a variable depending on one of the previous assigned variables.
```javascript
// bad
- var i, len, dragonball,
+ let i, len, dragonball,
items = getItems(),
goSportsTeam = true;
// bad
- var i;
- var items = getItems();
- var dragonball;
- var goSportsTeam = true;
- var len;
+ let i;
+ const items = getItems();
+ let dragonball;
+ const goSportsTeam = true;
+ let len;
// good
- var items = getItems();
- var goSportsTeam = true;
- var dragonball;
- var length;
- var i;
+ const goSportsTeam = true;
+ const items = getItems();
+ let dragonball;
+ let i;
+ let length;
```
- - Assign variables at the top of their scope. This helps avoid issues with variable declaration and assignment hoisting related issues.
-
- ```javascript
- // bad
- function() {
- test();
- console.log('doing stuff..');
-
- //..other stuff..
-
- var name = getName();
+ - Assign variables where you need them, but place them in a reasonable place.
- if (name === 'test') {
- return false;
- }
-
- return name;
- }
+ > Why? `let` and `const` are block scoped and not function scoped.
+ ```javascript
// good
function() {
- var name = getName();
-
test();
console.log('doing stuff..');
//..other stuff..
+ const name = getName();
+
if (name === 'test') {
return false;
}
@@ -449,10 +932,10 @@
}
// bad - unnessary function call
- function() {
- var name = getName();
+ function(hasName) {
+ const name = getName();
- if (!arguments.length) {
+ if (!hasName) {
return false;
}
@@ -462,14 +945,12 @@
}
// good
- function() {
- var name;
-
- if (!arguments.length) {
+ function(hasName) {
+ if (!hasName) {
return false;
}
- name = getName();
+ const name = getName();
this.setFirstName(name);
return true;
@@ -481,7 +962,7 @@
## Hoisting
- - Variable declarations get hoisted to the top of their scope, but their assignment does not.
+ - `var` declarations get hoisted to the top of their scope, their assignment does not. `const` and `let` declarations are blessed with a new concept called [Temporal Dead Zones (TDZ)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#Temporal_dead_zone_and_errors_with_let). It's important to know why [typeof is no longer safe](http://es-discourse.com/t/why-typeof-is-no-longer-safe/15).
```javascript
// we know this wouldn't work (assuming there
@@ -503,10 +984,17 @@
// declaration to the top of the scope,
// which means our example could be rewritten as:
function example() {
- var declaredButNotAssigned;
+ let declaredButNotAssigned;
console.log(declaredButNotAssigned); // => undefined
declaredButNotAssigned = true;
}
+
+ // using const and let
+ function example() {
+ console.log(declaredButNotAssigned); // => throws a ReferenceError
+ console.log(typeof declaredButNotAssigned); // => throws a ReferenceError
+ const declaredButNotAssigned = true;
+ }
```
- Anonymous function expressions hoist their variable name, but not the function assignment.
@@ -568,7 +1056,6 @@
**[⬆ back to top](#table-of-contents)**
-
## Comparison Operators & Equality
- Use `===` and `!==` over `==` and `!=`.
@@ -707,17 +1194,17 @@
```javascript
// bad
- var active = true; // is current tab
+ const active = true; // is current tab
// good
// is current tab
- var active = true;
+ const active = true;
// bad
function getType() {
console.log('fetching type...');
// set the default type to 'no type'
- var type = this._type || 'no type';
+ const type = this._type || 'no type';
return type;
}
@@ -727,7 +1214,7 @@
console.log('fetching type...');
// set the default type to 'no type'
- var type = this._type || 'no type';
+ const type = this._type || 'no type';
return type;
}
@@ -769,17 +1256,17 @@
```javascript
// bad
function() {
- ∙∙∙∙var name;
+ ∙∙∙∙const name;
}
// bad
function() {
- ∙var name;
+ ∙const name;
}
// good
function() {
- ∙∙var name;
+ ∙∙const name;
}
```
@@ -837,10 +1324,10 @@
```javascript
// bad
- var x=y+5;
+ const x=y+5;
// good
- var x = y + 5;
+ const x = y + 5;
```
- End files with a single newline character.
@@ -891,13 +1378,13 @@
.updateCount();
// bad
- var leds = stage.selectAll('.led').data(data).enter().append('svg:svg').classed('led', true)
+ const leds = stage.selectAll('.led').data(data).enter().append('svg:svg').class('led', true)
.attr('width', (radius + margin) * 2).append('svg:g')
.attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
.call(tron.led);
// good
- var leds = stage.selectAll('.led')
+ const leds = stage.selectAll('.led')
.data(data)
.enter().append('svg:svg')
.classed('led', true)
@@ -924,7 +1411,7 @@
return baz;
// bad
- var obj = {
+ const obj = {
foo: function() {
},
bar: function() {
@@ -933,7 +1420,7 @@
return obj;
// good
- var obj = {
+ const obj = {
foo: function() {
},
@@ -953,21 +1440,21 @@
```javascript
// bad
- var story = [
+ const story = [
once
, upon
, aTime
];
// good
- var story = [
+ const story = [
once,
upon,
aTime
];
// bad
- var hero = {
+ const hero = {
firstName: 'Bob'
, lastName: 'Parr'
, heroName: 'Mr. Incredible'
@@ -975,7 +1462,7 @@
};
// good
- var hero = {
+ const hero = {
firstName: 'Bob',
lastName: 'Parr',
heroName: 'Mr. Incredible',
@@ -989,23 +1476,23 @@
```javascript
// bad
- var hero = {
+ const hero = {
firstName: 'Kevin',
lastName: 'Flynn',
};
- var heroes = [
+ const heroes = [
'Batman',
'Superman',
];
// good
- var hero = {
+ const hero = {
firstName: 'Kevin',
lastName: 'Flynn'
};
- var heroes = [
+ const heroes = [
'Batman',
'Superman'
];
@@ -1021,19 +1508,19 @@
```javascript
// bad
(function() {
- var name = 'Skywalker'
+ const name = 'Skywalker'
return name
})()
// good
- (function() {
- var name = 'Skywalker';
+ (() => {
+ const name = 'Skywalker';
return name;
})();
// good (guards against the function becoming an argument when two files with IIFEs are concatenated)
- ;(function() {
- var name = 'Skywalker';
+ ;(() => {
+ const name = 'Skywalker';
return name;
})();
```
@@ -1052,40 +1539,34 @@
// => this.reviewScore = 9;
// bad
- var totalScore = this.reviewScore + '';
-
- // good
- var totalScore = '' + this.reviewScore;
-
- // bad
- var totalScore = '' + this.reviewScore + ' total score';
+ const totalScore = this.reviewScore + '';
// good
- var totalScore = this.reviewScore + ' total score';
+ const totalScore = String(this.reviewScore);
```
- Use `parseInt` for Numbers and always with a radix for type casting.
```javascript
- var inputValue = '4';
+ const inputValue = '4';
// bad
- var val = new Number(inputValue);
+ const val = new Number(inputValue);
// bad
- var val = +inputValue;
+ const val = +inputValue;
// bad
- var val = inputValue >> 0;
+ const val = inputValue >> 0;
// bad
- var val = parseInt(inputValue);
+ const val = parseInt(inputValue);
// good
- var val = Number(inputValue);
+ const val = Number(inputValue);
// good
- var val = parseInt(inputValue, 10);
+ const val = parseInt(inputValue, 10);
```
- If for whatever reason you are doing something wild and `parseInt` is your bottleneck and need to use Bitshift for [performance reasons](http://jsperf.com/coercion-vs-casting/3), leave a comment explaining why and what you're doing.
@@ -1097,7 +1578,7 @@
* Bitshifting the String to coerce it to a
* Number made it a lot faster.
*/
- var val = inputValue >> 0;
+ const val = inputValue >> 0;
```
- **Note:** Be careful when using bitshift operations. Numbers are represented as [64-bit values](http://es5.github.io/#x4.3.19), but Bitshift operations always return a 32-bit integer ([source](http://es5.github.io/#x11.7)). Bitshift can lead to unexpected behavior for integer values larger than 32 bits. [Discussion](https://github.com/airbnb/javascript/issues/109). Largest signed 32-bit Int is 2,147,483,647:
@@ -1111,16 +1592,16 @@
- Booleans:
```javascript
- var age = 0;
+ const age = 0;
// bad
- var hasAge = new Boolean(age);
+ const hasAge = new Boolean(age);
// good
- var hasAge = Boolean(age);
+ const hasAge = Boolean(age);
// good
- var hasAge = !!age;
+ const hasAge = !!age;
```
**[⬆ back to top](#table-of-contents)**
@@ -1146,13 +1627,12 @@
```javascript
// bad
- var OBJEcttsssss = {};
- var this_is_my_object = {};
- var o = {};
+ const OBJEcttsssss = {};
+ const this_is_my_object = {};
function c() {}
// good
- var thisIsMyObject = {};
+ const thisIsMyObject = {};
function thisIsMyFunction() {}
```
@@ -1164,16 +1644,18 @@
this.name = options.name;
}
- var bad = new user({
+ const bad = new user({
name: 'nope'
});
// good
- function User(options) {
- this.name = options.name;
+ class User {
+ constructor(options) {
+ this.name = options.name;
+ }
}
- var good = new User({
+ const good = new User({
name: 'yup'
});
```
@@ -1189,69 +1671,73 @@
this._firstName = 'Panda';
```
- - When saving a reference to `this` use `_this`.
+ - Don't save references to `this`. Use arrow functions or Function#bind.
```javascript
// bad
- function() {
- var self = this;
+ function foo() {
+ const self = this;
return function() {
console.log(self);
};
}
// bad
- function() {
- var that = this;
+ function foo() {
+ const that = this;
return function() {
console.log(that);
};
}
// good
- function() {
- var _this = this;
- return function() {
- console.log(_this);
+ function foo() {
+ return () => {
+ console.log(this);
};
}
```
- - Name your functions. This is helpful for stack traces.
-
- ```javascript
- // bad
- var log = function(msg) {
- console.log(msg);
- };
-
- // good
- var log = function log(msg) {
- console.log(msg);
- };
- ```
-
- - **Note:** IE8 and below exhibit some quirks with named function expressions. See [http://kangax.github.io/nfe/](http://kangax.github.io/nfe/) for more info.
-
- If your file exports a single class, your filename should be exactly the name of the class.
```javascript
// file contents
class CheckBox {
// ...
}
- module.exports = CheckBox;
+ export default CheckBox;
// in some other file
// bad
- var CheckBox = require('./checkBox');
+ import CheckBox from './checkBox';
// bad
- var CheckBox = require('./check_box');
+ import CheckBox from './check_box';
// good
- var CheckBox = require('./CheckBox');
+ import CheckBox from './CheckBox';
```
+ - Use camelCase when you export-default a function. Your filename should be identical to your function's name.
+
+ ```javascript
+ function makeStyleGuide() {
+ }
+
+ export default makeStyleGuide;
+ ```
+
+ - Use PascalCase when you export a singleton / function library / bare object.
+
+ ```javascript
+ const AirbnbStyleGuide = {
+ es6: {
+ }
+ };
+
+ export default AirbnbStyleGuide;
+ ```
+
+
**[⬆ back to top](#table-of-contents)**
@@ -1291,104 +1777,20 @@
- It's okay to create get() and set() functions, but be consistent.
```javascript
- function Jedi(options) {
- options || (options = {});
- var lightsaber = options.lightsaber || 'blue';
- this.set('lightsaber', lightsaber);
- }
-
- Jedi.prototype.set = function(key, val) {
- this[key] = val;
- };
-
- Jedi.prototype.get = function(key) {
- return this[key];
- };
- ```
-
-**[⬆ back to top](#table-of-contents)**
-
-
-## Constructors
-
- - Assign methods to the prototype object, instead of overwriting the prototype with a new object. Overwriting the prototype makes inheritance impossible: by resetting the prototype you'll overwrite the base!
-
- ```javascript
- function Jedi() {
- console.log('new jedi');
- }
-
- // bad
- Jedi.prototype = {
- fight: function fight() {
- console.log('fighting');
- },
-
- block: function block() {
- console.log('blocking');
+ class Jedi {
+ constructor(options = {}) {
+ const lightsaber = options.lightsaber || 'blue';
+ this.set('lightsaber', lightsaber);
}
- };
-
- // good
- Jedi.prototype.fight = function fight() {
- console.log('fighting');
- };
-
- Jedi.prototype.block = function block() {
- console.log('blocking');
- };
- ```
-
- - Methods can return `this` to help with method chaining.
-
- ```javascript
- // bad
- Jedi.prototype.jump = function() {
- this.jumping = true;
- return true;
- };
-
- Jedi.prototype.setHeight = function(height) {
- this.height = height;
- };
- var luke = new Jedi();
- luke.jump(); // => true
- luke.setHeight(20); // => undefined
-
- // good
- Jedi.prototype.jump = function() {
- this.jumping = true;
- return this;
- };
-
- Jedi.prototype.setHeight = function(height) {
- this.height = height;
- return this;
- };
-
- var luke = new Jedi();
-
- luke.jump()
- .setHeight(20);
- ```
-
-
- - It's okay to write a custom toString() method, just make sure it works successfully and causes no side effects.
+ set(key, val) {
+ this[key] = val;
+ }
- ```javascript
- function Jedi(options) {
- options || (options = {});
- this.name = options.name || 'no name';
+ get(key) {
+ return this[key];
+ }
}
-
- Jedi.prototype.getName = function getName() {
- return this.name;
- };
-
- Jedi.prototype.toString = function toString() {
- return 'Jedi - ' + this.getName();
- };
```
**[⬆ back to top](#table-of-contents)**
@@ -1398,7 +1800,7 @@
- When attaching data payloads to events (whether DOM events or something more proprietary like Backbone events), pass a hash instead of a raw value. This allows a subsequent contributor to add more data to the event payload without finding and updating every handler for the event. For example, instead of:
- ```js
+ ```javascript
// bad
$(this).trigger('listingUpdated', listing.id);
@@ -1411,7 +1813,7 @@
prefer:
- ```js
+ ```javascript
// good
$(this).trigger('listingUpdated', { listingId : listing.id });
@@ -1425,47 +1827,16 @@
**[⬆ back to top](#table-of-contents)**
-## Modules
-
- - The module should start with a `!`. This ensures that if a malformed module forgets to include a final semicolon there aren't errors in production when the scripts get concatenated. [Explanation](https://github.com/airbnb/javascript/issues/44#issuecomment-13063933)
- - The file should be named with camelCase, live in a folder with the same name, and match the name of the single export.
- - Add a method called `noConflict()` that sets the exported module to the previous version and returns this one.
- - Always declare `'use strict';` at the top of the module.
-
- ```javascript
- // fancyInput/fancyInput.js
-
- !function(global) {
- 'use strict';
-
- var previousFancyInput = global.FancyInput;
-
- function FancyInput(options) {
- this.options = options || {};
- }
-
- FancyInput.noConflict = function noConflict() {
- global.FancyInput = previousFancyInput;
- return FancyInput;
- };
-
- global.FancyInput = FancyInput;
- }(this);
- ```
-
-**[⬆ back to top](#table-of-contents)**
-
-
## jQuery
- Prefix jQuery object variables with a `$`.
```javascript
// bad
- var sidebar = $('.sidebar');
+ const sidebar = $('.sidebar');
// good
- var $sidebar = $('.sidebar');
+ const $sidebar = $('.sidebar');
```
- Cache jQuery lookups.
@@ -1484,7 +1855,7 @@
// good
function setSidebar() {
- var $sidebar = $('.sidebar');
+ const $sidebar = $('.sidebar');
$sidebar.hide();
// ...stuff...
@@ -1524,6 +1895,25 @@
**[⬆ back to top](#table-of-contents)**
+## ECMAScript 6 Styles
+
+This is a collection of links to the various es6 features.
+
+1. [Arrow Functions](#arrow-functions)
+1. [Classes](#constructors)
+1. [Object Shorthand](#es6-object-shorthand)
+1. [Object Concise](#es6-object-concise)
+1. [Object Computed Properties](#es6-computed-properties)
+1. [Template Strings](#es6-template-literals)
+1. [Destructuring](#destructuring)
+1. [Default Parameters](#es6-default-parameters)
+1. [Rest](#es6-rest)
+1. [Array Spreads](#es6-array-spreads)
+1. [Let and Const](#references)
+1. [Iterators and Generators](#iterators-and-generators)
+1. [Modules](#modules)
+
+**[⬆ back to top](#table-of-contents)**
## Testing
@@ -1554,6 +1944,12 @@
## Resources
+**Learning ES6**
+
+ - [Draft ECMA 2015 (ES6) Spec](https://people.mozilla.org/~jorendorff/es6-draft.html)
+ - [ExploringJS](http://exploringjs.com/)
+ - [ES6 Compatibility Table](https://kangax.github.io/compat-table/es6/)
+ - [Comprehensive Overview of ES6 Features](http://es6-features.org/)
**Read This**
@@ -1570,7 +1966,6 @@
- [Google JavaScript Style Guide](http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml)
- [jQuery Core Style Guidelines](http://docs.jquery.com/JQuery_Core_Style_Guidelines)
- [Principles of Writing Consistent, Idiomatic JavaScript](https://github.com/rwldrn/idiomatic.js/)
- - [JavaScript Standard Style](https://github.com/feross/standard)
**Other Styles**
@@ -1603,8 +1998,6 @@
- [JSBooks](http://jsbooks.revolunet.com/) - Julien Bouquillon
- [Third Party JavaScript](http://manning.com/vinegar/) - Ben Vinegar and Anton Kovalyov
- [Effective JavaScript: 68 Specific Ways to Harness the Power of JavaScript](http://amzn.com/0321812182) - David Herman
- - [Eloquent JavaScript](http://eloquentjavascript.net) - Marijn Haverbeke
- - [You Don't Know JS](https://github.com/getify/You-Dont-Know-JS) - Kyle Simpson
**Blogs**
@@ -1661,7 +2054,6 @@
- **National Geographic**: [natgeo/javascript](https://github.com/natgeo/javascript)
- **National Park Service**: [nationalparkservice/javascript](https://github.com/nationalparkservice/javascript)
- **Nimbl3**: [nimbl3/javascript](https://github.com/nimbl3/javascript)
- - **Nordic Venture Family**: [CodeDistillery/javascript](https://github.com/CodeDistillery/javascript)
- **Orion Health**: [orionhealth/javascript](https://github.com/orionhealth/javascript)
- **Peerby**: [Peerby/javascript](https://github.com/Peerby/javascript)
- **Razorfish**: [razorfish/javascript-style-guide](https://github.com/razorfish/javascript-style-guide)
diff --git a/es5/README.md b/es5/README.md
new file mode 100644
index 0000000000..02ecc75ee6
--- /dev/null
+++ b/es5/README.md
@@ -0,0 +1,1742 @@
+[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/airbnb/javascript?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
+
+# Airbnb JavaScript Style Guide() {
+
+*A mostly reasonable approach to JavaScript*
+
+
+## Table of Contents
+
+ 1. [Types](#types)
+ 1. [Objects](#objects)
+ 1. [Arrays](#arrays)
+ 1. [Strings](#strings)
+ 1. [Functions](#functions)
+ 1. [Properties](#properties)
+ 1. [Variables](#variables)
+ 1. [Hoisting](#hoisting)
+ 1. [Comparison Operators & Equality](#comparison-operators--equality)
+ 1. [Blocks](#blocks)
+ 1. [Comments](#comments)
+ 1. [Whitespace](#whitespace)
+ 1. [Commas](#commas)
+ 1. [Semicolons](#semicolons)
+ 1. [Type Casting & Coercion](#type-casting--coercion)
+ 1. [Naming Conventions](#naming-conventions)
+ 1. [Accessors](#accessors)
+ 1. [Constructors](#constructors)
+ 1. [Events](#events)
+ 1. [Modules](#modules)
+ 1. [jQuery](#jquery)
+ 1. [ECMAScript 5 Compatibility](#ecmascript-5-compatibility)
+ 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](#the-javascript-style-guide-guide)
+ 1. [Chat With Us About Javascript](#chat-with-us-about-javascript)
+ 1. [Contributors](#contributors)
+ 1. [License](#license)
+
+## Types
+
+ - **Primitives**: When you access a primitive type you work directly on its value.
+
+ + `string`
+ + `number`
+ + `boolean`
+ + `null`
+ + `undefined`
+
+ ```javascript
+ var foo = 1;
+ var 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.
+
+ + `object`
+ + `array`
+ + `function`
+
+ ```javascript
+ var foo = [1, 2];
+ var bar = foo;
+
+ bar[0] = 9;
+
+ console.log(foo[0], bar[0]); // => 9, 9
+ ```
+
+**[⬆ back to top](#table-of-contents)**
+
+## Objects
+
+ - Use the literal syntax for object creation.
+
+ ```javascript
+ // bad
+ var item = new Object();
+
+ // good
+ var item = {};
+ ```
+
+ - Don't use [reserved words](http://es5.github.io/#x7.6.1) as keys. It won't work in IE8. [More info](https://github.com/airbnb/javascript/issues/61).
+
+ ```javascript
+ // bad
+ var superman = {
+ default: { clark: 'kent' },
+ private: true
+ };
+
+ // good
+ var superman = {
+ defaults: { clark: 'kent' },
+ hidden: true
+ };
+ ```
+
+ - Use readable synonyms in place of reserved words.
+
+ ```javascript
+ // bad
+ var superman = {
+ class: 'alien'
+ };
+
+ // bad
+ var superman = {
+ klass: 'alien'
+ };
+
+ // good
+ var superman = {
+ type: 'alien'
+ };
+ ```
+
+**[⬆ back to top](#table-of-contents)**
+
+## Arrays
+
+ - Use the literal syntax for array creation.
+
+ ```javascript
+ // bad
+ var items = new Array();
+
+ // good
+ var items = [];
+ ```
+
+ - Use Array#push instead of direct assignment to add items to an array.
+
+ ```javascript
+ var someStack = [];
+
+
+ // bad
+ someStack[someStack.length] = 'abracadabra';
+
+ // good
+ someStack.push('abracadabra');
+ ```
+
+ - 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;
+ var itemsCopy = [];
+ var i;
+
+ // bad
+ for (i = 0; i < len; i++) {
+ itemsCopy[i] = items[i];
+ }
+
+ // good
+ itemsCopy = items.slice();
+ ```
+
+ - To convert an array-like object to an array, use Array#slice.
+
+ ```javascript
+ function trigger() {
+ var args = Array.prototype.slice.call(arguments);
+ ...
+ }
+ ```
+
+**[⬆ back to top](#table-of-contents)**
+
+
+## Strings
+
+ - Use single quotes `''` for strings.
+
+ ```javascript
+ // bad
+ var name = "Bob Parr";
+
+ // good
+ var name = 'Bob Parr';
+
+ // bad
+ var fullName = "Bob " + this.lastName;
+
+ // good
+ 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).
+
+ ```javascript
+ // bad
+ var errorMessage = 'This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.';
+
+ // bad
+ var errorMessage = 'This is a super long error that was thrown because \
+ of Batman. When you stop to think about how Batman had anything to do \
+ with this, you would get nowhere \
+ fast.';
+
+ // good
+ var errorMessage = 'This is a super long error that was thrown because ' +
+ 'of Batman. When you stop to think about how Batman had anything to do ' +
+ 'with this, you would get nowhere fast.';
+ ```
+
+ - When programmatically 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;
+ var messages;
+ var length;
+ var i;
+
+ messages = [{
+ state: 'success',
+ message: 'This one worked.'
+ }, {
+ state: 'success',
+ message: 'This one worked as well.'
+ }, {
+ state: 'error',
+ message: 'This one did not work.'
+ }];
+
+ length = messages.length;
+
+ // bad
+ function inbox(messages) {
+ items = '';
+
+ for (i = 0; i < length; i++) {
+ items += '- ' + messages[i].message + '
';
+ }
+
+ return items + '
';
+ }
+
+ // good
+ function inbox(messages) {
+ items = [];
+
+ for (i = 0; i < length; i++) {
+ // use direct assignment in this case because we're micro-optimizing.
+ items[i] = '' + messages[i].message + '';
+ }
+
+ return '';
+ }
+ ```
+
+**[⬆ back to top](#table-of-contents)**
+
+
+## Functions
+
+ - Function expressions:
+
+ ```javascript
+ // anonymous function expression
+ var anonymous = function() {
+ return true;
+ };
+
+ // named function expression
+ var named = function named() {
+ return true;
+ };
+
+ // immediately-invoked function expression (IIFE)
+ (function() {
+ console.log('Welcome to the Internet. Please follow me.');
+ })();
+ ```
+
+ - Never declare a function in a non-function block (if, while, etc). Assign the function to a variable instead. Browsers will allow you to do it, but they all interpret it differently, which is bad news bears.
+ - **Note:** ECMA-262 defines a `block` as a list of statements. A function declaration is not a statement. [Read ECMA-262's note on this issue](http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf#page=97).
+
+ ```javascript
+ // bad
+ if (currentUser) {
+ function test() {
+ console.log('Nope.');
+ }
+ }
+
+ // good
+ var test;
+ if (currentUser) {
+ test = function test() {
+ console.log('Yup.');
+ };
+ }
+ ```
+
+ - Never name a parameter `arguments`. This will take precedence over the `arguments` object that is given to every function scope.
+
+ ```javascript
+ // bad
+ function nope(name, options, arguments) {
+ // ...stuff...
+ }
+
+ // good
+ function yup(name, options, args) {
+ // ...stuff...
+ }
+ ```
+
+**[⬆ back to top](#table-of-contents)**
+
+
+
+## Properties
+
+ - Use dot notation when accessing properties.
+
+ ```javascript
+ var luke = {
+ jedi: true,
+ age: 28
+ };
+
+ // bad
+ var isJedi = luke['jedi'];
+
+ // good
+ var isJedi = luke.jedi;
+ ```
+
+ - Use subscript notation `[]` when accessing properties with a variable.
+
+ ```javascript
+ var luke = {
+ jedi: true,
+ age: 28
+ };
+
+ function getProp(prop) {
+ return luke[prop];
+ }
+
+ var isJedi = getProp('jedi');
+ ```
+
+**[⬆ back to top](#table-of-contents)**
+
+
+## Variables
+
+ - Always use `var` to declare variables. Not doing so will result in global variables. We want to avoid polluting the global namespace. Captain Planet warned us of that.
+
+ ```javascript
+ // bad
+ superPower = new SuperPower();
+
+ // good
+ var superPower = new SuperPower();
+ ```
+
+ - Use one `var` declaration per variable.
+ It's easier to add new variable declarations this way, and you never have
+ to worry about swapping out a `;` for a `,` or introducing punctuation-only
+ diffs.
+
+ ```javascript
+ // bad
+ var items = getItems(),
+ goSportsTeam = true,
+ dragonball = 'z';
+
+ // bad
+ // (compare to above, and try to spot the mistake)
+ var items = getItems(),
+ goSportsTeam = true;
+ dragonball = 'z';
+
+ // good
+ var items = getItems();
+ var goSportsTeam = true;
+ var dragonball = 'z';
+ ```
+
+ - Declare unassigned variables last. This is helpful when later on you might need to assign a variable depending on one of the previous assigned variables.
+
+ ```javascript
+ // bad
+ var i, len, dragonball,
+ items = getItems(),
+ goSportsTeam = true;
+
+ // bad
+ var i;
+ var items = getItems();
+ var dragonball;
+ var goSportsTeam = true;
+ var len;
+
+ // good
+ var items = getItems();
+ var goSportsTeam = true;
+ var dragonball;
+ var length;
+ var i;
+ ```
+
+ - Assign variables at the top of their scope. This helps avoid issues with variable declaration and assignment hoisting related issues.
+
+ ```javascript
+ // bad
+ function() {
+ test();
+ console.log('doing stuff..');
+
+ //..other stuff..
+
+ var name = getName();
+
+ if (name === 'test') {
+ return false;
+ }
+
+ return name;
+ }
+
+ // good
+ function() {
+ var name = getName();
+
+ test();
+ console.log('doing stuff..');
+
+ //..other stuff..
+
+ if (name === 'test') {
+ return false;
+ }
+
+ return name;
+ }
+
+ // bad - unnessary function call
+ function() {
+ var name = getName();
+
+ if (!arguments.length) {
+ return false;
+ }
+
+ this.setFirstName(name);
+
+ return true;
+ }
+
+ // good
+ function() {
+ var name;
+
+ if (!arguments.length) {
+ return false;
+ }
+
+ name = getName();
+ this.setFirstName(name);
+
+ return true;
+ }
+ ```
+
+**[⬆ back to top](#table-of-contents)**
+
+
+## Hoisting
+
+ - Variable declarations get hoisted to the top of their scope, but their assignment does not.
+
+ ```javascript
+ // we know this wouldn't work (assuming there
+ // is no notDefined global variable)
+ function example() {
+ console.log(notDefined); // => throws a ReferenceError
+ }
+
+ // creating a variable declaration after you
+ // reference the variable will work due to
+ // variable hoisting. Note: the assignment
+ // value of `true` is not hoisted.
+ function example() {
+ console.log(declaredButNotAssigned); // => undefined
+ var declaredButNotAssigned = true;
+ }
+
+ // The interpreter is hoisting the variable
+ // declaration to the top of the scope,
+ // which means our example could be rewritten as:
+ function example() {
+ var declaredButNotAssigned;
+ console.log(declaredButNotAssigned); // => undefined
+ declaredButNotAssigned = true;
+ }
+ ```
+
+ - Anonymous function expressions hoist their variable name, but not the function assignment.
+
+ ```javascript
+ function example() {
+ console.log(anonymous); // => undefined
+
+ anonymous(); // => TypeError anonymous is not a function
+
+ var anonymous = function() {
+ console.log('anonymous function expression');
+ };
+ }
+ ```
+
+ - Named function expressions hoist the variable name, not the function name or the function body.
+
+ ```javascript
+ function example() {
+ console.log(named); // => undefined
+
+ named(); // => TypeError named is not a function
+
+ superPower(); // => ReferenceError superPower is not defined
+
+ var named = function superPower() {
+ console.log('Flying');
+ };
+ }
+
+ // the same is true when the function name
+ // is the same as the variable name.
+ function example() {
+ console.log(named); // => undefined
+
+ named(); // => TypeError named is not a function
+
+ var named = function named() {
+ console.log('named');
+ }
+ }
+ ```
+
+ - Function declarations hoist their name and the function body.
+
+ ```javascript
+ function example() {
+ superPower(); // => Flying
+
+ function superPower() {
+ console.log('Flying');
+ }
+ }
+ ```
+
+ - For more information refer to [JavaScript Scoping & Hoisting](http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting) by [Ben Cherry](http://www.adequatelygood.com/).
+
+**[⬆ back to top](#table-of-contents)**
+
+
+
+## Comparison Operators & Equality
+
+ - Use `===` and `!==` over `==` and `!=`.
+ - Comparison operators are evaluated using coercion with the `ToBoolean` method and always follow these simple rules:
+
+ + **Objects** evaluate to **true**
+ + **Undefined** evaluates to **false**
+ + **Null** evaluates to **false**
+ + **Booleans** evaluate to **the value of the boolean**
+ + **Numbers** evaluate to **false** if **+0, -0, or NaN**, otherwise **true**
+ + **Strings** evaluate to **false** if an empty string `''`, otherwise **true**
+
+ ```javascript
+ if ([0]) {
+ // true
+ // An array is an object, objects evaluate to true
+ }
+ ```
+
+ - Use shortcuts.
+
+ ```javascript
+ // bad
+ if (name !== '') {
+ // ...stuff...
+ }
+
+ // good
+ if (name) {
+ // ...stuff...
+ }
+
+ // bad
+ if (collection.length > 0) {
+ // ...stuff...
+ }
+
+ // good
+ if (collection.length) {
+ // ...stuff...
+ }
+ ```
+
+ - For more information see [Truth Equality and JavaScript](http://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/#more-2108) by Angus Croll.
+
+**[⬆ back to top](#table-of-contents)**
+
+
+## Blocks
+
+ - Use braces with all multi-line blocks.
+
+ ```javascript
+ // bad
+ if (test)
+ return false;
+
+ // good
+ if (test) return false;
+
+ // good
+ if (test) {
+ return false;
+ }
+
+ // bad
+ function() { return false; }
+
+ // good
+ function() {
+ return false;
+ }
+ ```
+
+ - If you're using multi-line blocks with `if` and `else`, put `else` on the same line as your
+ `if` block's closing brace.
+
+ ```javascript
+ // bad
+ if (test) {
+ thing1();
+ thing2();
+ }
+ else {
+ thing3();
+ }
+
+ // good
+ if (test) {
+ thing1();
+ thing2();
+ } else {
+ thing3();
+ }
+ ```
+
+
+**[⬆ back to top](#table-of-contents)**
+
+
+## Comments
+
+ - Use `/** ... */` for multi-line comments. Include a description, specify types and values for all parameters and return values.
+
+ ```javascript
+ // bad
+ // make() returns a new element
+ // based on the passed in tag name
+ //
+ // @param {String} tag
+ // @return {Element} element
+ function make(tag) {
+
+ // ...stuff...
+
+ return element;
+ }
+
+ // good
+ /**
+ * make() returns a new element
+ * based on the passed in tag name
+ *
+ * @param {String} tag
+ * @return {Element} element
+ */
+ function make(tag) {
+
+ // ...stuff...
+
+ return element;
+ }
+ ```
+
+ - Use `//` for single line comments. Place single line comments on a newline above the subject of the comment. Put an empty line before the comment.
+
+ ```javascript
+ // bad
+ var active = true; // is current tab
+
+ // good
+ // is current tab
+ var active = true;
+
+ // bad
+ function getType() {
+ console.log('fetching type...');
+ // set the default type to 'no type'
+ var type = this._type || 'no type';
+
+ return type;
+ }
+
+ // good
+ function getType() {
+ console.log('fetching type...');
+
+ // set the default type to 'no type'
+ var type = this._type || 'no type';
+
+ return type;
+ }
+ ```
+
+ - Prefixing your comments with `FIXME` or `TODO` helps other developers quickly understand if you're pointing out a problem that needs to be revisited, or if you're suggesting a solution to the problem that needs to be implemented. These are different than regular comments because they are actionable. The actions are `FIXME -- need to figure this out` or `TODO -- need to implement`.
+
+ - Use `// FIXME:` to annotate problems.
+
+ ```javascript
+ function Calculator() {
+
+ // FIXME: shouldn't use a global here
+ total = 0;
+
+ return this;
+ }
+ ```
+
+ - Use `// TODO:` to annotate solutions to problems.
+
+ ```javascript
+ function Calculator() {
+
+ // TODO: total should be configurable by an options param
+ this.total = 0;
+
+ return this;
+ }
+ ```
+
+**[⬆ back to top](#table-of-contents)**
+
+
+## Whitespace
+
+ - Use soft tabs set to 2 spaces.
+
+ ```javascript
+ // bad
+ function() {
+ ∙∙∙∙var name;
+ }
+
+ // bad
+ function() {
+ ∙var name;
+ }
+
+ // good
+ function() {
+ ∙∙var name;
+ }
+ ```
+
+ - Place 1 space before the leading brace.
+
+ ```javascript
+ // bad
+ function test(){
+ console.log('test');
+ }
+
+ // good
+ function test() {
+ console.log('test');
+ }
+
+ // bad
+ dog.set('attr',{
+ age: '1 year',
+ breed: 'Bernese Mountain Dog'
+ });
+
+ // good
+ dog.set('attr', {
+ age: '1 year',
+ breed: 'Bernese Mountain Dog'
+ });
+ ```
+
+ - Place 1 space before the opening parenthesis in control statements (`if`, `while` etc.). Place no space before the argument list in function calls and declarations.
+
+ ```javascript
+ // bad
+ if(isJedi) {
+ fight ();
+ }
+
+ // good
+ if (isJedi) {
+ fight();
+ }
+
+ // bad
+ function fight () {
+ console.log ('Swooosh!');
+ }
+
+ // good
+ function fight() {
+ console.log('Swooosh!');
+ }
+ ```
+
+ - Set off operators with spaces.
+
+ ```javascript
+ // bad
+ var x=y+5;
+
+ // good
+ var x = y + 5;
+ ```
+
+ - End files with a single newline character.
+
+ ```javascript
+ // bad
+ (function(global) {
+ // ...stuff...
+ })(this);
+ ```
+
+ ```javascript
+ // bad
+ (function(global) {
+ // ...stuff...
+ })(this);↵
+ ↵
+ ```
+
+ ```javascript
+ // good
+ (function(global) {
+ // ...stuff...
+ })(this);↵
+ ```
+
+ - Use indentation when making long method chains. Use a leading dot, which
+ emphasizes that the line is a method call, not a new statement.
+
+ ```javascript
+ // bad
+ $('#items').find('.selected').highlight().end().find('.open').updateCount();
+
+ // bad
+ $('#items').
+ find('.selected').
+ highlight().
+ end().
+ find('.open').
+ updateCount();
+
+ // good
+ $('#items')
+ .find('.selected')
+ .highlight()
+ .end()
+ .find('.open')
+ .updateCount();
+
+ // bad
+ var leds = stage.selectAll('.led').data(data).enter().append('svg:svg').classed('led', true)
+ .attr('width', (radius + margin) * 2).append('svg:g')
+ .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
+ .call(tron.led);
+
+ // good
+ var leds = stage.selectAll('.led')
+ .data(data)
+ .enter().append('svg:svg')
+ .classed('led', true)
+ .attr('width', (radius + margin) * 2)
+ .append('svg:g')
+ .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
+ .call(tron.led);
+ ```
+
+ - Leave a blank line after blocks and before the next statement
+
+ ```javascript
+ // bad
+ if (foo) {
+ return bar;
+ }
+ return baz;
+
+ // good
+ if (foo) {
+ return bar;
+ }
+
+ return baz;
+
+ // bad
+ var obj = {
+ foo: function() {
+ },
+ bar: function() {
+ }
+ };
+ return obj;
+
+ // good
+ var obj = {
+ foo: function() {
+ },
+
+ bar: function() {
+ }
+ };
+
+ return obj;
+ ```
+
+
+**[⬆ back to top](#table-of-contents)**
+
+## Commas
+
+ - Leading commas: **Nope.**
+
+ ```javascript
+ // bad
+ var story = [
+ once
+ , upon
+ , aTime
+ ];
+
+ // good
+ var story = [
+ once,
+ upon,
+ aTime
+ ];
+
+ // bad
+ var hero = {
+ firstName: 'Bob'
+ , lastName: 'Parr'
+ , heroName: 'Mr. Incredible'
+ , superPower: 'strength'
+ };
+
+ // good
+ var hero = {
+ firstName: 'Bob',
+ lastName: 'Parr',
+ heroName: 'Mr. Incredible',
+ superPower: 'strength'
+ };
+ ```
+
+ - Additional trailing comma: **Nope.** This can cause problems with IE6/7 and IE9 if it's in quirksmode. Also, in some implementations of ES3 would add length to an array if it had an additional trailing comma. This was clarified in ES5 ([source](http://es5.github.io/#D)):
+
+ > Edition 5 clarifies the fact that a trailing comma at the end of an ArrayInitialiser does not add to the length of the array. This is not a semantic change from Edition 3 but some implementations may have previously misinterpreted this.
+
+ ```javascript
+ // bad
+ var hero = {
+ firstName: 'Kevin',
+ lastName: 'Flynn',
+ };
+
+ var heroes = [
+ 'Batman',
+ 'Superman',
+ ];
+
+ // good
+ var hero = {
+ firstName: 'Kevin',
+ lastName: 'Flynn'
+ };
+
+ var heroes = [
+ 'Batman',
+ 'Superman'
+ ];
+ ```
+
+**[⬆ back to top](#table-of-contents)**
+
+
+## Semicolons
+
+ - **Yup.**
+
+ ```javascript
+ // bad
+ (function() {
+ var name = 'Skywalker'
+ return name
+ })()
+
+ // good
+ (function() {
+ var name = 'Skywalker';
+ return name;
+ })();
+
+ // good (guards against the function becoming an argument when two files with IIFEs are concatenated)
+ ;(function() {
+ var name = 'Skywalker';
+ return name;
+ })();
+ ```
+
+ [Read more](http://stackoverflow.com/a/7365214/1712802).
+
+**[⬆ back to top](#table-of-contents)**
+
+
+## Type Casting & Coercion
+
+ - Perform type coercion at the beginning of the statement.
+ - Strings:
+
+ ```javascript
+ // => this.reviewScore = 9;
+
+ // bad
+ var totalScore = this.reviewScore + '';
+
+ // good
+ var totalScore = '' + this.reviewScore;
+
+ // bad
+ var totalScore = '' + this.reviewScore + ' total score';
+
+ // good
+ var totalScore = this.reviewScore + ' total score';
+ ```
+
+ - Use `parseInt` for Numbers and always with a radix for type casting.
+
+ ```javascript
+ var inputValue = '4';
+
+ // bad
+ var val = new Number(inputValue);
+
+ // bad
+ var val = +inputValue;
+
+ // bad
+ var val = inputValue >> 0;
+
+ // bad
+ var val = parseInt(inputValue);
+
+ // good
+ var val = Number(inputValue);
+
+ // good
+ var val = parseInt(inputValue, 10);
+ ```
+
+ - If for whatever reason you are doing something wild and `parseInt` is your bottleneck and need to use Bitshift for [performance reasons](http://jsperf.com/coercion-vs-casting/3), leave a comment explaining why and what you're doing.
+
+ ```javascript
+ // good
+ /**
+ * parseInt was the reason my code was slow.
+ * Bitshifting the String to coerce it to a
+ * Number made it a lot faster.
+ */
+ var val = inputValue >> 0;
+ ```
+
+ - **Note:** Be careful when using bitshift operations. Numbers are represented as [64-bit values](http://es5.github.io/#x4.3.19), but Bitshift operations always return a 32-bit integer ([source](http://es5.github.io/#x11.7)). Bitshift can lead to unexpected behavior for integer values larger than 32 bits. [Discussion](https://github.com/airbnb/javascript/issues/109). Largest signed 32-bit Int is 2,147,483,647:
+
+ ```javascript
+ 2147483647 >> 0 //=> 2147483647
+ 2147483648 >> 0 //=> -2147483648
+ 2147483649 >> 0 //=> -2147483647
+ ```
+
+ - Booleans:
+
+ ```javascript
+ var age = 0;
+
+ // bad
+ var hasAge = new Boolean(age);
+
+ // good
+ var hasAge = Boolean(age);
+
+ // good
+ var hasAge = !!age;
+ ```
+
+**[⬆ back to top](#table-of-contents)**
+
+
+## Naming Conventions
+
+ - Avoid single letter names. Be descriptive with your naming.
+
+ ```javascript
+ // bad
+ function q() {
+ // ...stuff...
+ }
+
+ // good
+ function query() {
+ // ..stuff..
+ }
+ ```
+
+ - Use camelCase when naming objects, functions, and instances.
+
+ ```javascript
+ // bad
+ var OBJEcttsssss = {};
+ var this_is_my_object = {};
+ var o = {};
+ function c() {}
+
+ // good
+ var thisIsMyObject = {};
+ function thisIsMyFunction() {}
+ ```
+
+ - Use PascalCase when naming constructors or classes.
+
+ ```javascript
+ // bad
+ function user(options) {
+ this.name = options.name;
+ }
+
+ var bad = new user({
+ name: 'nope'
+ });
+
+ // good
+ function User(options) {
+ this.name = options.name;
+ }
+
+ var good = new User({
+ name: 'yup'
+ });
+ ```
+
+ - Use a leading underscore `_` when naming private properties.
+
+ ```javascript
+ // bad
+ this.__firstName__ = 'Panda';
+ this.firstName_ = 'Panda';
+
+ // good
+ this._firstName = 'Panda';
+ ```
+
+ - When saving a reference to `this` use `_this`.
+
+ ```javascript
+ // bad
+ function() {
+ var self = this;
+ return function() {
+ console.log(self);
+ };
+ }
+
+ // bad
+ function() {
+ var that = this;
+ return function() {
+ console.log(that);
+ };
+ }
+
+ // good
+ function() {
+ var _this = this;
+ return function() {
+ console.log(_this);
+ };
+ }
+ ```
+
+ - Name your functions. This is helpful for stack traces.
+
+ ```javascript
+ // bad
+ var log = function(msg) {
+ console.log(msg);
+ };
+
+ // good
+ var log = function log(msg) {
+ console.log(msg);
+ };
+ ```
+
+ - **Note:** IE8 and below exhibit some quirks with named function expressions. See [http://kangax.github.io/nfe/](http://kangax.github.io/nfe/) for more info.
+
+ - If your file exports a single class, your filename should be exactly the name of the class.
+ ```javascript
+ // file contents
+ class CheckBox {
+ // ...
+ }
+ module.exports = CheckBox;
+
+ // in some other file
+ // bad
+ var CheckBox = require('./checkBox');
+
+ // bad
+ var CheckBox = require('./check_box');
+
+ // good
+ var CheckBox = require('./CheckBox');
+ ```
+
+**[⬆ back to top](#table-of-contents)**
+
+
+## Accessors
+
+ - Accessor functions for properties are not required.
+ - If you do make accessor functions use getVal() and setVal('hello').
+
+ ```javascript
+ // bad
+ dragon.age();
+
+ // good
+ dragon.getAge();
+
+ // bad
+ dragon.age(25);
+
+ // good
+ dragon.setAge(25);
+ ```
+
+ - If the property is a boolean, use isVal() or hasVal().
+
+ ```javascript
+ // bad
+ if (!dragon.age()) {
+ return false;
+ }
+
+ // good
+ if (!dragon.hasAge()) {
+ return false;
+ }
+ ```
+
+ - It's okay to create get() and set() functions, but be consistent.
+
+ ```javascript
+ function Jedi(options) {
+ options || (options = {});
+ var lightsaber = options.lightsaber || 'blue';
+ this.set('lightsaber', lightsaber);
+ }
+
+ Jedi.prototype.set = function(key, val) {
+ this[key] = val;
+ };
+
+ Jedi.prototype.get = function(key) {
+ return this[key];
+ };
+ ```
+
+**[⬆ back to top](#table-of-contents)**
+
+
+## Constructors
+
+ - Assign methods to the prototype object, instead of overwriting the prototype with a new object. Overwriting the prototype makes inheritance impossible: by resetting the prototype you'll overwrite the base!
+
+ ```javascript
+ function Jedi() {
+ console.log('new jedi');
+ }
+
+ // bad
+ Jedi.prototype = {
+ fight: function fight() {
+ console.log('fighting');
+ },
+
+ block: function block() {
+ console.log('blocking');
+ }
+ };
+
+ // good
+ Jedi.prototype.fight = function fight() {
+ console.log('fighting');
+ };
+
+ Jedi.prototype.block = function block() {
+ console.log('blocking');
+ };
+ ```
+
+ - Methods can return `this` to help with method chaining.
+
+ ```javascript
+ // bad
+ Jedi.prototype.jump = function() {
+ this.jumping = true;
+ return true;
+ };
+
+ Jedi.prototype.setHeight = function(height) {
+ this.height = height;
+ };
+
+ var luke = new Jedi();
+ luke.jump(); // => true
+ luke.setHeight(20); // => undefined
+
+ // good
+ Jedi.prototype.jump = function() {
+ this.jumping = true;
+ return this;
+ };
+
+ Jedi.prototype.setHeight = function(height) {
+ this.height = height;
+ return this;
+ };
+
+ var luke = new Jedi();
+
+ luke.jump()
+ .setHeight(20);
+ ```
+
+
+ - It's okay to write a custom toString() method, just make sure it works successfully and causes no side effects.
+
+ ```javascript
+ function Jedi(options) {
+ options || (options = {});
+ this.name = options.name || 'no name';
+ }
+
+ Jedi.prototype.getName = function getName() {
+ return this.name;
+ };
+
+ Jedi.prototype.toString = function toString() {
+ return 'Jedi - ' + this.getName();
+ };
+ ```
+
+**[⬆ back to top](#table-of-contents)**
+
+
+## Events
+
+ - When attaching data payloads to events (whether DOM events or something more proprietary like Backbone events), pass a hash instead of a raw value. This allows a subsequent contributor to add more data to the event payload without finding and updating every handler for the event. For example, instead of:
+
+ ```js
+ // bad
+ $(this).trigger('listingUpdated', listing.id);
+
+ ...
+
+ $(this).on('listingUpdated', function(e, listingId) {
+ // do something with listingId
+ });
+ ```
+
+ prefer:
+
+ ```js
+ // good
+ $(this).trigger('listingUpdated', { listingId : listing.id });
+
+ ...
+
+ $(this).on('listingUpdated', function(e, data) {
+ // do something with data.listingId
+ });
+ ```
+
+ **[⬆ back to top](#table-of-contents)**
+
+
+## Modules
+
+ - The module should start with a `!`. This ensures that if a malformed module forgets to include a final semicolon there aren't errors in production when the scripts get concatenated. [Explanation](https://github.com/airbnb/javascript/issues/44#issuecomment-13063933)
+ - The file should be named with camelCase, live in a folder with the same name, and match the name of the single export.
+ - Add a method called `noConflict()` that sets the exported module to the previous version and returns this one.
+ - Always declare `'use strict';` at the top of the module.
+
+ ```javascript
+ // fancyInput/fancyInput.js
+
+ !function(global) {
+ 'use strict';
+
+ var previousFancyInput = global.FancyInput;
+
+ function FancyInput(options) {
+ this.options = options || {};
+ }
+
+ FancyInput.noConflict = function noConflict() {
+ global.FancyInput = previousFancyInput;
+ return FancyInput;
+ };
+
+ global.FancyInput = FancyInput;
+ }(this);
+ ```
+
+**[⬆ back to top](#table-of-contents)**
+
+
+## jQuery
+
+ - Prefix jQuery object variables with a `$`.
+
+ ```javascript
+ // bad
+ var sidebar = $('.sidebar');
+
+ // good
+ var $sidebar = $('.sidebar');
+ ```
+
+ - Cache jQuery lookups.
+
+ ```javascript
+ // bad
+ function setSidebar() {
+ $('.sidebar').hide();
+
+ // ...stuff...
+
+ $('.sidebar').css({
+ 'background-color': 'pink'
+ });
+ }
+
+ // good
+ function setSidebar() {
+ var $sidebar = $('.sidebar');
+ $sidebar.hide();
+
+ // ...stuff...
+
+ $sidebar.css({
+ 'background-color': 'pink'
+ });
+ }
+ ```
+
+ - For DOM queries use Cascading `$('.sidebar ul')` or parent > child `$('.sidebar > ul')`. [jsPerf](http://jsperf.com/jquery-find-vs-context-sel/16)
+ - Use `find` with scoped jQuery object queries.
+
+ ```javascript
+ // bad
+ $('ul', '.sidebar').hide();
+
+ // bad
+ $('.sidebar').find('ul').hide();
+
+ // good
+ $('.sidebar ul').hide();
+
+ // good
+ $('.sidebar > ul').hide();
+
+ // good
+ $sidebar.find('ul').hide();
+ ```
+
+**[⬆ back to top](#table-of-contents)**
+
+
+## ECMAScript 5 Compatibility
+
+ - Refer to [Kangax](https://twitter.com/kangax/)'s ES5 [compatibility table](http://kangax.github.com/es5-compat-table/).
+
+**[⬆ back to top](#table-of-contents)**
+
+
+## Testing
+
+ - **Yup.**
+
+ ```javascript
+ function() {
+ return true;
+ }
+ ```
+
+**[⬆ back to top](#table-of-contents)**
+
+
+## Performance
+
+ - [On Layout & Web Performance](http://kellegous.com/j/2013/01/26/layout-performance/)
+ - [String vs Array Concat](http://jsperf.com/string-vs-array-concat/2)
+ - [Try/Catch Cost In a Loop](http://jsperf.com/try-catch-in-loop-cost)
+ - [Bang Function](http://jsperf.com/bang-function)
+ - [jQuery Find vs Context, Selector](http://jsperf.com/jquery-find-vs-context-sel/13)
+ - [innerHTML vs textContent for script text](http://jsperf.com/innerhtml-vs-textcontent-for-script-text)
+ - [Long String Concatenation](http://jsperf.com/ya-string-concat)
+ - Loading...
+
+**[⬆ back to top](#table-of-contents)**
+
+
+## Resources
+
+
+**Read This**
+
+ - [Annotated ECMAScript 5.1](http://es5.github.com/)
+
+**Tools**
+
+ - Code Style Linters
+ + [JSHint](http://www.jshint.com/) - [Airbnb Style .jshintrc](https://github.com/airbnb/javascript/blob/master/linters/jshintrc)
+ + [JSCS](https://github.com/jscs-dev/node-jscs) - [Airbnb Style Preset](https://github.com/jscs-dev/node-jscs/blob/master/presets/airbnb.json)
+
+**Other Styleguides**
+
+ - [Google JavaScript Style Guide](http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml)
+ - [jQuery Core Style Guidelines](http://docs.jquery.com/JQuery_Core_Style_Guidelines)
+ - [Principles of Writing Consistent, Idiomatic JavaScript](https://github.com/rwldrn/idiomatic.js/)
+ - [JavaScript Standard Style](https://github.com/feross/standard)
+
+**Other Styles**
+
+ - [Naming this in nested functions](https://gist.github.com/4135065) - Christian Johansen
+ - [Conditional Callbacks](https://github.com/airbnb/javascript/issues/52) - Ross Allen
+ - [Popular JavaScript Coding Conventions on Github](http://sideeffect.kr/popularconvention/#javascript) - JeongHoon Byun
+ - [Multiple var statements in JavaScript, not superfluous](http://benalman.com/news/2012/05/multiple-var-statements-javascript/) - Ben Alman
+
+**Further Reading**
+
+ - [Understanding JavaScript Closures](http://javascriptweblog.wordpress.com/2010/10/25/understanding-javascript-closures/) - Angus Croll
+ - [Basic JavaScript for the impatient programmer](http://www.2ality.com/2013/06/basic-javascript.html) - Dr. Axel Rauschmayer
+ - [You Might Not Need jQuery](http://youmightnotneedjquery.com/) - Zack Bloom & Adam Schwartz
+ - [ES6 Features](https://github.com/lukehoban/es6features) - Luke Hoban
+ - [Frontend Guidelines](https://github.com/bendc/frontend-guidelines) - Benjamin De Cock
+
+**Books**
+
+ - [JavaScript: The Good Parts](http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742) - Douglas Crockford
+ - [JavaScript Patterns](http://www.amazon.com/JavaScript-Patterns-Stoyan-Stefanov/dp/0596806752) - Stoyan Stefanov
+ - [Pro JavaScript Design Patterns](http://www.amazon.com/JavaScript-Design-Patterns-Recipes-Problem-Solution/dp/159059908X) - Ross Harmes and Dustin Diaz
+ - [High Performance Web Sites: Essential Knowledge for Front-End Engineers](http://www.amazon.com/High-Performance-Web-Sites-Essential/dp/0596529309) - Steve Souders
+ - [Maintainable JavaScript](http://www.amazon.com/Maintainable-JavaScript-Nicholas-C-Zakas/dp/1449327680) - Nicholas C. Zakas
+ - [JavaScript Web Applications](http://www.amazon.com/JavaScript-Web-Applications-Alex-MacCaw/dp/144930351X) - Alex MacCaw
+ - [Pro JavaScript Techniques](http://www.amazon.com/Pro-JavaScript-Techniques-John-Resig/dp/1590597273) - John Resig
+ - [Smashing Node.js: JavaScript Everywhere](http://www.amazon.com/Smashing-Node-js-JavaScript-Everywhere-Magazine/dp/1119962595) - Guillermo Rauch
+ - [Secrets of the JavaScript Ninja](http://www.amazon.com/Secrets-JavaScript-Ninja-John-Resig/dp/193398869X) - John Resig and Bear Bibeault
+ - [Human JavaScript](http://humanjavascript.com/) - Henrik Joreteg
+ - [Superhero.js](http://superherojs.com/) - Kim Joar Bekkelund, Mads Mobæk, & Olav Bjorkoy
+ - [JSBooks](http://jsbooks.revolunet.com/) - Julien Bouquillon
+ - [Third Party JavaScript](http://manning.com/vinegar/) - Ben Vinegar and Anton Kovalyov
+ - [Effective JavaScript: 68 Specific Ways to Harness the Power of JavaScript](http://amzn.com/0321812182) - David Herman
+ - [Eloquent JavaScript](http://eloquentjavascript.net) - Marijn Haverbeke
+ - [You Don't Know JS](https://github.com/getify/You-Dont-Know-JS) - Kyle Simpson
+
+**Blogs**
+
+ - [DailyJS](http://dailyjs.com/)
+ - [JavaScript Weekly](http://javascriptweekly.com/)
+ - [JavaScript, JavaScript...](http://javascriptweblog.wordpress.com/)
+ - [Bocoup Weblog](http://weblog.bocoup.com/)
+ - [Adequately Good](http://www.adequatelygood.com/)
+ - [NCZOnline](http://www.nczonline.net/)
+ - [Perfection Kills](http://perfectionkills.com/)
+ - [Ben Alman](http://benalman.com/)
+ - [Dmitry Baranovskiy](http://dmitry.baranovskiy.com/)
+ - [Dustin Diaz](http://dustindiaz.com/)
+ - [nettuts](http://net.tutsplus.com/?s=javascript)
+
+**Podcasts**
+
+ - [JavaScript Jabber](http://devchat.tv/js-jabber/)
+
+
+**[⬆ back to top](#table-of-contents)**
+
+## In the Wild
+
+ This is a list of organizations that are using this style guide. Send us a pull request or open an issue and we'll add you to the list.
+
+ - **Aan Zee**: [AanZee/javascript](https://github.com/AanZee/javascript)
+ - **Adult Swim**: [adult-swim/javascript](https://github.com/adult-swim/javascript)
+ - **Airbnb**: [airbnb/javascript](https://github.com/airbnb/javascript)
+ - **American Insitutes for Research**: [AIRAST/javascript](https://github.com/AIRAST/javascript)
+ - **Apartmint**: [apartmint/javascript](https://github.com/apartmint/javascript)
+ - **Avalara**: [avalara/javascript](https://github.com/avalara/javascript)
+ - **Compass Learning**: [compasslearning/javascript-style-guide](https://github.com/compasslearning/javascript-style-guide)
+ - **DailyMotion**: [dailymotion/javascript](https://github.com/dailymotion/javascript)
+ - **Digitpaint** [digitpaint/javascript](https://github.com/digitpaint/javascript)
+ - **Evernote**: [evernote/javascript-style-guide](https://github.com/evernote/javascript-style-guide)
+ - **ExactTarget**: [ExactTarget/javascript](https://github.com/ExactTarget/javascript)
+ - **Flexberry**: [Flexberry/javascript-style-guide](https://github.com/Flexberry/javascript-style-guide)
+ - **Gawker Media**: [gawkermedia/javascript](https://github.com/gawkermedia/javascript)
+ - **GeneralElectric**: [GeneralElectric/javascript](https://github.com/GeneralElectric/javascript)
+ - **GoodData**: [gooddata/gdc-js-style](https://github.com/gooddata/gdc-js-style)
+ - **Grooveshark**: [grooveshark/javascript](https://github.com/grooveshark/javascript)
+ - **How About We**: [howaboutwe/javascript](https://github.com/howaboutwe/javascript)
+ - **InfoJobs**: [InfoJobs/JavaScript-Style-Guide](https://github.com/InfoJobs/JavaScript-Style-Guide)
+ - **Intent Media**: [intentmedia/javascript](https://github.com/intentmedia/javascript)
+ - **Jam3**: [Jam3/Javascript-Code-Conventions](https://github.com/Jam3/Javascript-Code-Conventions)
+ - **JSSolutions**: [JSSolutions/javascript](https://github.com/JSSolutions/javascript)
+ - **Kinetica Solutions**: [kinetica/javascript](https://github.com/kinetica/javascript)
+ - **Mighty Spring**: [mightyspring/javascript](https://github.com/mightyspring/javascript)
+ - **MinnPost**: [MinnPost/javascript](https://github.com/MinnPost/javascript)
+ - **ModCloth**: [modcloth/javascript](https://github.com/modcloth/javascript)
+ - **Money Advice Service**: [moneyadviceservice/javascript](https://github.com/moneyadviceservice/javascript)
+ - **Muber**: [muber/javascript](https://github.com/muber/javascript)
+ - **National Geographic**: [natgeo/javascript](https://github.com/natgeo/javascript)
+ - **National Park Service**: [nationalparkservice/javascript](https://github.com/nationalparkservice/javascript)
+ - **Nimbl3**: [nimbl3/javascript](https://github.com/nimbl3/javascript)
+ - **Nordic Venture Family**: [CodeDistillery/javascript](https://github.com/CodeDistillery/javascript)
+ - **Orion Health**: [orionhealth/javascript](https://github.com/orionhealth/javascript)
+ - **Peerby**: [Peerby/javascript](https://github.com/Peerby/javascript)
+ - **Razorfish**: [razorfish/javascript-style-guide](https://github.com/razorfish/javascript-style-guide)
+ - **reddit**: [reddit/styleguide/javascript](https://github.com/reddit/styleguide/tree/master/javascript)
+ - **REI**: [reidev/js-style-guide](https://github.com/reidev/js-style-guide)
+ - **Ripple**: [ripple/javascript-style-guide](https://github.com/ripple/javascript-style-guide)
+ - **SeekingAlpha**: [seekingalpha/javascript-style-guide](https://github.com/seekingalpha/javascript-style-guide)
+ - **Shutterfly**: [shutterfly/javascript](https://github.com/shutterfly/javascript)
+ - **StudentSphere**: [studentsphere/javascript](https://github.com/studentsphere/javascript)
+ - **Target**: [target/javascript](https://github.com/target/javascript)
+ - **TheLadders**: [TheLadders/javascript](https://github.com/TheLadders/javascript)
+ - **T4R Technology**: [T4R-Technology/javascript](https://github.com/T4R-Technology/javascript)
+ - **Userify**: [userify/javascript](https://github.com/userify/javascript)
+ - **VoxFeed**: [VoxFeed/javascript-style-guide](https://github.com/VoxFeed/javascript-style-guide)
+ - **Weggo**: [Weggo/javascript](https://github.com/Weggo/javascript)
+ - **Zillow**: [zillow/javascript](https://github.com/zillow/javascript)
+ - **ZocDoc**: [ZocDoc/javascript](https://github.com/ZocDoc/javascript)
+
+## Translation
+
+ This style guide is also available in other languages:
+
+ - ![br](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Brazil.png) **Brazilian Portuguese**: [armoucar/javascript-style-guide](https://github.com/armoucar/javascript-style-guide)
+ - ![bg](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Bulgaria.png) **Bulgarian**: [borislavvv/javascript](https://github.com/borislavvv/javascript)
+ - ![ca](https://raw.githubusercontent.com/fpmweb/javascript-style-guide/master/img/catala.png) **Catalan**: [fpmweb/javascript-style-guide](https://github.com/fpmweb/javascript-style-guide)
+ - ![tw](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Taiwan.png) **Chinese(Traditional)**: [jigsawye/javascript](https://github.com/jigsawye/javascript)
+ - ![cn](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/China.png) **Chinese(Simplified)**: [adamlu/javascript-style-guide](https://github.com/adamlu/javascript-style-guide)
+ - ![fr](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/France.png) **French**: [nmussy/javascript-style-guide](https://github.com/nmussy/javascript-style-guide)
+ - ![de](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Germany.png) **German**: [timofurrer/javascript-style-guide](https://github.com/timofurrer/javascript-style-guide)
+ - ![it](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Italy.png) **Italian**: [sinkswim/javascript-style-guide](https://github.com/sinkswim/javascript-style-guide)
+ - ![jp](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Japan.png) **Japanese**: [mitsuruog/javacript-style-guide](https://github.com/mitsuruog/javacript-style-guide)
+ - ![kr](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/South-Korea.png) **Korean**: [tipjs/javascript-style-guide](https://github.com/tipjs/javascript-style-guide)
+ - ![pl](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Poland.png) **Polish**: [mjurczyk/javascript](https://github.com/mjurczyk/javascript)
+ - ![ru](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Russia.png) **Russian**: [uprock/javascript](https://github.com/uprock/javascript)
+ - ![es](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Spain.png) **Spanish**: [paolocarrasco/javascript-style-guide](https://github.com/paolocarrasco/javascript-style-guide)
+ - ![th](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Thailand.png) **Thai**: [lvarayut/javascript-style-guide](https://github.com/lvarayut/javascript-style-guide)
+
+## The JavaScript Style Guide Guide
+
+ - [Reference](https://github.com/airbnb/javascript/wiki/The-JavaScript-Style-Guide-Guide)
+
+## Chat With Us About JavaScript
+
+ - Find us on [gitter](https://gitter.im/airbnb/javascript).
+
+## Contributors
+
+ - [View Contributors](https://github.com/airbnb/javascript/graphs/contributors)
+
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2014 Airbnb
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**[⬆ back to top](#table-of-contents)**
+
+# };
diff --git a/linters/jshintrc b/linters/jshintrc
index cc6e398b40..141067fd23 100644
--- a/linters/jshintrc
+++ b/linters/jshintrc
@@ -13,6 +13,9 @@
// Define globals exposed by Node.js.
"node": true,
+ // Allow ES6.
+ "esnext": true,
+
/*
* ENFORCING OPTIONS
* =================