์๋ฌธ:https://github.com/airbnb/javascript
- Types
- Objects
- Arrays
- Strings
- Functions
- Properties
- Variables
- Hoisting
- Conditional Expressions & Equality
- Blocks
- Comments
- Whitespace
- Commas
- Semicolons
- Type Casting & Coercion
- Naming Conventions
- Accessors
- Constructors
- Events
- Modules
- jQuery
- ES5 Compatibility
- Testing
- Performance
- Resources
- In the Wild
- Translation
- The JavaScript Style Guide Guide
- Contributors
- License
-
Primitives: primitive type์ ๊ทธ ๊ฐ์ ์ง์ ์กฐ์ํฉ๋๋ค.
string
number
boolean
null
undefined
var foo = 1, bar = foo; bar = 9; console.log(foo, bar); // => 1, 9
-
Complex: ์ฐธ์กฐํ(Complex)์ ์ฐธ์กฐ๋ฅผ ํตํด ๊ฐ์ ์กฐ์ํฉ๋๋ค.
object
array
function
var foo = [1, 2], bar = foo; bar[0] = 9; console.log(foo[0], bar[0]); // => 9, 9
-
Object๋ฅผ ๋ง๋ค ๋๋ ๋ฆฌํฐ๋ด ๊ตฌ๋ฌธ์ ์ฌ์ฉํ์ญ์์ค.
// bad var item = new Object(); // good var item = {};
-
์์ฝ์ด(reserved words)๋ฅผ ํค๋ก ์ฌ์ฉํ์ง ๋ง์ญ์์ค. ์ด๊ฒ์ IE8์์ ๋์ํ์ง ์์ต๋๋ค. More info
// bad var superman = { default: { clark: 'kent' }, private: true }; // good var superman = { defaults: { clark: 'kent' }, hidden: true };
-
์์ฝ์ด ๋์ ์๊ธฐ ์ฌ์ด ๋์์ด(readable synonyms)๋ฅผ ์ฌ์ฉํ์ญ์์ค.
// bad var superman = { class: 'alien' }; // bad var superman = { klass: 'alien' }; // good var superman = { type: 'alien' };
-
๋ฐฐ์ด์ ๋ง๋ค ๋ ๋ฆฌํฐ๋ด ๊ตฌ๋ฌธ์ ์ฌ์ฉํ์ญ์์ค.
// bad var items = new Array(); // good var items = [];
-
๊ธธ์ด๋ฅผ ์ ์์๋ ๊ฒฝ์ฐ๋ Array#push๋ฅผ ์ฌ์ฉํ์ญ์์ค.
var someStack = []; // bad someStack[someStack.length] = 'abracadabra'; // good someStack.push('abracadabra');
-
๋ฐฐ์ด์ ๋ณต์ฌ ํ ํ์๊ฐ์๋ ๊ฒฝ์ฐ Array#slice๋ฅผ ์ฌ์ฉํ์ญ์์ค. jsPerf
var len = items.length, itemsCopy = [], i; // bad for (i = 0; i < len; i++) { itemsCopy[i] = items[i]; } // good itemsCopy = items.slice();
-
Array์ ๋น์ทํ(Array-Like)ํ Object๋ฅผ Array์ ๋ณํํ๋ ๊ฒฝ์ฐ๋ Array#slice๋ฅผ ์ฌ์ฉํ์ญ์์ค.
function trigger() { var args = Array.prototype.slice.call(arguments); ... }
-
๋ฌธ์์ด์ ์์ ๋ฐ์ดํ
''
๋ฅผ ์ฌ์ฉํ์ญ์์ค.// bad var name = "Bob Parr"; // good var name = 'Bob Parr'; // bad var fullName = "Bob " + this.lastName; // good var fullName = 'Bob ' + this.lastName;
-
80 ๋ฌธ์ ์ด์์ ๋ฌธ์์ด์ ๋ฌธ์์ด ์ฐ๊ฒฐ์ ์ฌ์ฉํ์ฌ ์ฌ๋ฌ ์ค์ ๊ฑธ์ณ ๊ธฐ์ ํ ํ์๊ฐ ์์ต๋๋ค.
-
Note : ๋ฌธ์์ด ์ฐ๊ฒฐ์ ๋ง์ดํ๋ฉด ์ฑ๋ฅ์ ์ํฅ์ ์ค ์ ์์ต๋๋ค. jsPerf & Discussion
// 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.';
-
ํ๋ก๊ทธ๋จ์์ ๋ฌธ์์ด์ ์์ฑ ํ ํ์๊ฐ ์๋ ๊ฒฝ์ฐ (ํนํ IE๋) ๋ฌธ์์ด ์ฐ๊ฒฐ ๋์ Array#join์ ์ฌ์ฉํ์ญ์์ค. jsPerf.
var items, messages, length, 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 = '<ul>'; for (i = 0; i < length; i++) { items += '<li>' + messages[i].message + '</li>'; } return items + '</ul>'; } // good function inbox(messages) { items = []; for (i = 0; i < length; i++) { items[i] = messages[i].message; } return '<ul><li>' + items.join('</li><li>') + '</li></ul>'; }
-
ํจ์์(Function expressions)
// ์ต๋ช ํจ์์(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.'); })();
-
(if ๋ฐ while ๋ฑ) ๋ธ๋ก ๋ด์์ ๋ณ์์ ํจ์๋ฅผ ํ ๋นํ๋ ๋์ ํจ์๋ฅผ ์ ์ธํ์ง ๋ง์ญ์์ค. ๋ธ๋ผ์ฐ์ ๋ ํ์ฉํ์ง๋ง (๋ง์น 'bad news bears'์ฒ๋ผ) ๋ชจ๋ ๋ค๋ฅธ ๋ฐฉ์์ผ๋ก ํด์๋ฉ๋๋ค.
-
Note: ECMA-262์์๋
block
์ statements์ ๋ชฉ๋ก์ ์ ์๋์ด ์์ต๋๋ค ๋ง, ํจ์ ์ ์ธ์ statements๊ฐ ์์ต๋๋ค. ์ด ๋ฌธ์ ๋ ECMA-262์ ์ค๋ช ์ ์ฐธ์กฐํ์ญ์์ค. .// bad if (currentUser) { function test() { console.log('Nope.'); } } // good var test; if (currentUser) { test = function test() { console.log('Yup.'); }; }
-
๋งค๊ฐ ๋ณ์(parameter)์
arguments
๋ฅผ ์ ๋ ์ง์ ํ์ง ๋ง์ญ์์ค. ์ด๊ฒ์ ํจ์ ๋ฒ์๋ก ์ ๋ฌ ๋arguments
๊ฐ์ฒด์ ์ฐธ์กฐ๋ฅผ ๋ฎ์ด ์ธ ๊ฒ์ ๋๋ค.// bad function nope(name, options, arguments) { // ...stuff... } // good function yup(name, options, args) { // ...stuff... }
-
์์ฑ์ ์ก์ธ์คํ๋ ค๋ฉด ๋ํธ
.
๋ฅผ ์ฌ์ฉํ์ญ์์ค.var luke = { jedi: true, age: 28 }; // bad var isJedi = luke['jedi']; // good var isJedi = luke.jedi;
-
๋ณ์๋ฅผ ์ฌ์ฉํ์ฌ ์์ฑ์ ์ ๊ทผํ๋ ค๋ฉด ๋๊ดํธ
[]
์ ์ฌ์ฉํ์ญ์์ค.var luke = { jedi: true, age: 28 }; function getProp(prop) { return luke[prop]; } var isJedi = getProp('jedi');
-
๋ณ์๋ฅผ ์ ์ธ ํ ๋๋ ํญ์
var
๋ฅผ ์ฌ์ฉํ์ญ์์ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ์ ์ญ ๋ณ์๋ก ์ ์ธ๋ฉ๋๋ค. ์ ์ญ ๋ค์ ์คํ์ด์ค๋ฅผ ์ค์ผ์ํค์ง ์๋๋ก Captain Planet๋ ๊ฒฝ๊ณ ํ๊ณ ์์ต๋๋ค.// bad superPower = new SuperPower(); // good var superPower = new SuperPower();
-
์ฌ๋ฌ ๋ณ์๋ฅผ ์ ์ธํ๋ ค๋ฉด ํ๋์
var
๋ฅผ ์ฌ์ฉํ์ฌ ๋ณ์๋ง๋ค ์ค๋ฐ๊ฟํ์ฌ ์ ์ธํ์ญ์์ค.// bad var items = getItems(); var goSportsTeam = true; var dragonball = 'z'; // good var items = getItems(), goSportsTeam = true, dragonball = 'z';
-
์ ์๋์ง ์์ ๋ณ์๋ฅผ ๋ง์ง๋ง์ผ๋ก ์ ์ธํ์ญ์์ค. ์ด๊ฒ์ ๋์ค์ ์ด๋ฏธ ํ ๋น๋ ๋ณ์ ์ค ํ๋๋ฅผ ์ง์ ํด์ผํ๋ ๊ฒฝ์ฐ์ ์ ์ฉํฉ๋๋ค.
// bad var i, len, dragonball, items = getItems(), goSportsTeam = true; // bad var i, items = getItems(), dragonball, goSportsTeam = true, len; // good var items = getItems(), goSportsTeam = true, dragonball, length, i;
-
๋ณ์์ ํ ๋น์ ์ค์ฝํ์ ์์ ๋ถ๋ถ์์ ํด์ฃผ์ญ์์ค. ์ด๊ฒ์ ๋ณ์ ์ ์ธ๊ณผ Hoisting ๊ด๋ จ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํฉ๋๋ค.
// 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 function() { var name = getName(); if (!arguments.length) { return false; } return true; } // good function() { if (!arguments.length) { return false; } var name = getName(); return true; }
-
ํด๋น ์ค์ฝํ์ ์์ ๋ถ๋ถ์ Hoist๋ ๋ณ์์ ์ธ์ ํ ๋น๋์ง ์์ต๋๋ค.
// (notDefined๊ฐ ์ ์ญ ๋ณ์์ ์กด์ฌํ์ง ์๋๋ค๊ณ ๊ฐ์ ํ์ ๊ฒฝ์ฐ) // ์ด๊ฒ์ ๋์ํ์ง ์์ต๋๋ค. function example() { console.log(notDefined); // => throws a ReferenceError } // ๊ทธ ๋ณ์๋ฅผ ์ฐธ์กฐํ๋ ์ฝ๋ ํ์ ๊ทธ ๋ณ์๋ฅผ ์ ์ธ ํ ๊ฒฝ์ฐ // ๋ณ์๊ฐ Hoist๋ ์ํ์์ ์๋ํฉ๋๋ค. // Note : `true`๋ผ๋ ๊ฐ ์์ฒด๋ Hoist๋์ง ์์ต๋๋ค. function example() { console.log(declaredButNotAssigned); // => undefined var declaredButNotAssigned = true; } // ์ธํฐ ํ๋ฆฐํฐ๋ ๋ณ์ ์ ์ธ์ ์ค์ฝํ์ ์์ ๋ถ๋ถ์ Hoistํฉ๋๋ค. // ์์ ์๋ ๋ค์๊ณผ ๊ฐ์ด ๋ค์ ์์ฑํ ์ ์์ต๋๋ค. function example() { var declaredButNotAssigned; console.log(declaredButNotAssigned); // => undefined declaredButNotAssigned = true; }
-
์ต๋ช ํจ์์ ๊ฒฝ์ฐ ํจ์๊ฐ ํ ๋น๋๊ธฐ ์ ์ ๋ณ์๊ฐ Hoist๋ ์ ์์ต๋๋ค.
function example() { console.log(anonymous); // => undefined anonymous(); // => TypeError anonymous is not a function var anonymous = function() { console.log('anonymous function expression'); }; }
-
๋ช ๋ช ๋ ํจ์์ ๊ฒฝ์ฐ๋ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ณ์๊ฐ Hoist๋ ์ ์์ต๋๋ค. ํจ์ ์ด๋ฆ๊ณผ ํจ์ ๋ณธ์ฒด๋ Hoist๋์ง ์์ต๋๋ค.
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'); }; } // ํจ์์ด๋ฆ๊ณผ ๋ณ์์ด๋ฆ์ด ๊ฐ์ ๊ฒฝ์ฐ์๋ ๊ฐ์ ์ผ์ด ์ผ์ด๋ฉ๋๋ค. function example() { console.log(named); // => undefined named(); // => TypeError named is not a function var named = function named() { console.log('named'); } }
-
ํจ์ ์ ์ธ์ ํจ์์ด๋ฆ๊ณผ ํจ์๋ณธ๋ฌธ์ด Hoist๋ฉ๋๋ค.
function example() { superPower(); // => Flying function superPower() { console.log('Flying'); } }
-
๋ ์์ธํ ์ ๋ณด๋ Ben Cherry์ JavaScript Scoping & Hoisting๋ฅผ ์ฐธ์กฐํ์ญ์์ค.
-
==
๋!=
๋ณด๋ค๋===
์!==
๋ฅผ ์ฌ์ฉํด ์ฃผ์ญ์์ค -
์กฐ๊ฑด์์
ToBoolean
๋ฉ์๋์ ์ํด ์๋ฐํ๊ฒ ๋น๊ต๋ฉ๋๋ค. ํญ์ ์ด ๊ฐ๋จํ ๊ท์น์ ๋ฐ๋ผ ์ฃผ์ญ์์ค.- Objects ๋ true ๋ก ํ๊ฐ๋ฉ๋๋ค.
- undefined ๋ false ๋ก ํ๊ฐ๋ฉ๋๋ค.
- null ๋ false ๋ก ํ๊ฐ๋ฉ๋๋ค.
- Booleans ๋ booleanํ์ ๊ฐ ์ผ๋ก ํ๊ฐ๋ฉ๋๋ค.
- Numbers ๋ true ๋ก ํ๊ฐ๋ฉ๋๋ค. ํ์ง๋ง +0, -0, or NaN ์ ๊ฒฝ์ฐ๋ false ์ ๋๋ค.
- Strings ๋ true ๋ก ํ๊ฐ๋ฉ๋๋ค. ํ์ง๋ง ๋น๋ฌธ์
''
์ ๊ฒฝ์ฐ๋ false ์ ๋๋ค.
if ([0]) { // true // Array๋ Object ์ด๋ฏ๋ก true ๋ก ํ๊ฐ๋ฉ๋๋ค. }
-
์งง์ํ์์ ์ฌ์ฉํ์ญ์์ค.
// bad if (name !== '') { // ...stuff... } // good if (name) { // ...stuff... } // bad if (collection.length > 0) { // ...stuff... } // good if (collection.length) { // ...stuff... }
-
๋ ์์ธํ ์ ๋ณด๋ Angus Croll ์ Truth Equality and JavaScript๋ฅผ ์ฐธ๊ณ ํด ์ฃผ์ญ์์ค.
-
๋ณต์ํ ๋ธ๋ก์ ์ค๊ดํธ ({})๋ฅผ ์ฌ์ฉํ์ญ์์ค.
// bad if (test) return false; // good if (test) return false; // good if (test) { return false; } // bad function() { return false; } // good function() { return false; }
-
๋ณต์ํ์ ์ฝ๋ฉํธ๋
/** ... */
๋ฅผ ์ฌ์ฉํด ์ฃผ์ญ์์ค. ๊ทธ ์์๋ ์ค๋ช ๊ณผ ๋ชจ๋ ๋งค๊ฐ ๋ณ์์ ๋ฐํ ๊ฐ์ ๋ํ ํ์๊ณผ ๊ฐ์ ์ค๋ช ํฉ๋๋ค.// 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; }
-
ํ ์ค ์ฃผ์์๋
//
๋ฅผ ์ฌ์ฉํ์ญ์์ค. ์ฝ๋ฉํธ๋ฅผ ์ถ๊ฐํ๊ณ ์ถ์ ์ฝ๋์ ์๋จ์ ์์ฑํ์ญ์์ค. ๋ํ ์ฃผ์ ์์ ๋น ์ค์ ๋ฃ์ด์ฃผ์ญ์์ค.// 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; }
-
๋ฌธ์ ๋ฅผ ์ง์ ํ๊ณ ์ฌ๊ณ ๋ฅผ ์ด๊ตฌํ๊ฑฐ๋ ๋ฌธ์ ์ ๋ํ ํด๊ฒฐ์ฑ ์ ์ ์ํ๋ ๋ฑ ์๊ฒฌ์ ์์
FIXME
๋TODO
๋ฅผ ๋ถ์ด๋ ๊ฒ์ผ๋ก ๋ค๋ฅธ ๊ฐ๋ฐ์์ ๋น ๋ฅธ ์ดํด๋ฅผ ๋์ธ ์ ์์ต๋๋ค. ์ด๋ฌํ ์ด๋ค ์ก์ ์ ๋๋ฐํ๋ค๋ ์๋ฏธ์์ ์ผ๋ฐ ์ฝ๋ฉํธ์๋ ๋ค๋ฆ ๋๋ค. ์ก์ ์FIXME - ํด๊ฒฐ์ฑ ์ด ํ์
๋๋TODO - ๊ตฌํ์ด ํ์
์ ๋๋ค. -
๋ฌธ์ ์ ๋ํ ์ฝ๋ฉํธ๋ก
// FIXME :
๋ฅผ ์ฌ์ฉํ์ญ์์ค.function Calculator() { // FIXME: ์ ์ญ ๋ณ์๋ฅผ ์ฌ์ฉํด์๋ ์๋ฉ๋๋ค. total = 0; return this; }
-
๋ฌธ์ ํด๊ฒฐ์ฑ ์ ๋ํ ์ฝ๋ฉํธ๋ก
// TODO :
๋ฅผ ์ฌ์ฉํ์ญ์์ค.function Calculator() { // TODO: total์ ์ต์ ๋งค๊ฐ ๋ณ์๋ก ์ค์ ๋์ด์ผ ํจ. this.total = 0; return this; }
**[[โฌ]](#TOC)**
## <a name='whitespace'>Whitespace</a> [์๋ฌธ](https://github.com/airbnb/javascript#whitespace)
- ํญ์๋ ๊ณต๋ฐฑ 2๊ฐ๋ฅผ ์ค์ ํ์ญ์์ค.
```javascript
// bad
function() {
โโโโvar name;
}
// bad
function() {
โvar name;
}
// good
function() {
โโvar name;
}
```
- ์ค๊ดํธ({})์ ์์ ๊ณต๋ฐฑ์ ํ๋ ๋ฃ์ด์ฃผ์ญ์์ค.
```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'
});
```
- ํ์ผ์ ๋ง์ง๋ง์๋ ๋น ์ค์ ํ๋ ๋ฃ์ด์ฃผ์ญ์์ค.
```javascript
// bad
(function(global) {
// ...stuff...
})(this);
```
```javascript
// good
(function(global) {
// ...stuff...
})(this);
```
- ๋ฉ์๋ ์ฒด์ธ์ด ๊ธธ์ด์ง๋ ๊ฒฝ์ฐ ์ ์ ํ ๋ค์ฌ์ฐ๊ธฐ(indentation) ํ์ญ์์ค.
```javascript
// 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').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')
.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);
```
**[[โฌ]](#TOC)**
## <a name='commas'>Commas</a> [์๋ฌธ](https://github.com/airbnb/javascript#commas)
- ์ ๋์ comma๋ **ํ์ง๋ง์ญ์์ค.**
```javascript
// bad
var once
, upon
, aTime;
// good
var 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'
};
```
ใ- ๋ง๋ฏธ์ ๋ถํ์ํ ์ผํ๋ **ํ์ง ๋ง์ญ์์ค.** ์ด๊ฒ์ IE6/7๊ณผ quirksmode์ IE9์์ ๋ฌธ์ ๋ฅผ ์ผ์ผํฌ ์ ์์ต๋๋ค.
๋ํ ES3์ ์ผ๋ถ ๊ตฌํ์์ ๋ถํ์ํ ์ผํ๊ฐ ์๋ ๊ฒฝ์ฐ, ๋ฐฐ์ด ๊ธธ์ด๋ฅผ ์ถ๊ฐํฉ๋๋ค.
์ด๊ฒ์ ES5์์ ๋ถ๋ช
ํด์ก์ต๋๋ค.([source](http://es5.github.io/#D)):
> ์ 5 ํ์์๋ ๋ง๋ฏธ์ ๋ถํ์ํ ์ผํ๊ฐ ์๋ ArrayInitialiser (๋ฐฐ์ด ์ด๊ธฐํ ์ฐ์ฐ์)๋ผ๋ ๋ฐฐ์ด์ ๊ธธ์ด๋ฅผ ์ถ๊ฐํ์ง ์๋๋ค๋ ์ฌ์ค์ ๋ช
ํํํ๊ณ ์์ต๋๋ค. ์ด๊ฒ์ ์ 3 ํ์์ ์๋ฏธ์ ์ธ ๋ณ๊ฒฝ์ ์๋๋๋ค๋ง, ์ผ๋ถ์ ๊ตฌํ์ ์ด์ ๋ถํฐ ์ด๊ฒ์ ์คํดํ๊ณ ์์์์ง๋ ๋ชจ๋ฆ
๋๋ค.
```javascript
// bad
var hero = {
firstName: 'Kevin',
lastName: 'Flynn',
};
var heroes = [
'Batman',
'Superman',
];
// good
var hero = {
firstName: 'Kevin',
lastName: 'Flynn'
};
var heroes = [
'Batman',
'Superman'
];
```
**[[โฌ]](#TOC)**
## <a name='semicolons'>Semicolons</a> [์๋ฌธ](https://github.com/airbnb/javascript#semicolons)
- **๋ค!(Yup.)**
```javascript
// bad
(function() {
var name = 'Skywalker'
return name
})()
// good
(function() {
var name = 'Skywalker';
return name;
})();
// good
;(function() {
var name = 'Skywalker';
return name;
})();
```
**[[โฌ]](#TOC)**
## <a name='type-coercion'>Type Casting & Coercion(๊ฐ์ )</a> [์๋ฌธ](https://github.com/airbnb/javascript#type-coercion)
- ๋ฌธ์ ์์ ๋ถ๋ถ์์ ํ์ ๊ฐ์ ํฉ๋๋ค.
- 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';
```
- ์ซ์๋`parseInt`๋ฅผ ์ฌ์ฉํ์ญ์์ค. ํญ์ ํ๋ณํ์ ์ํ ๊ธฐ์(radix)๋ฅผ ์ธ์๋ก ์ ๋ฌํ์ญ์์ค.
```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);
```
- ์ด๋ค ์ด์ ์ ์ํด `parseInt` ๊ฐ ๋ณ๋ชฉ์ด ๋๊ณ , [์ฑ๋ฅ์ ์ธ ์ด์ ](http://jsperf.com/coercion-vs-casting/3)๋ก Bitshift๋ฅผ ์ฌ์ฉํ ํ์๊ฐ ์์ ๊ฒฝ์ฐ,
ํ๋ ค๊ณ ํ๋๊ฒ์ ๋ํด, why(์)์ what(๋ฌด์)์ ์ค๋ช
์ ์ฝ๋ฉํธ๋ก ๋จ๊ฒจ์ฃผ์ญ์์ค.
```javascript
// good
/**
* parseInt๊ฐ ๋ณ๋ชฉ์ ์ผ์ผํค๋ฏ๋ก
* Bitshift๋ก ๋ฌธ์์ด์ ์์น๋ก ๊ฐ์ ์ ์ผ๋ก ๋ณํํ๋ ๋ฐฉ๋ฒ์ผ๋ก
* ์ฑ๋ฅ์ ๊ฐ์ ์ํต๋๋ค.
*/
var val = inputValue >> 0;
```
- Booleans:
```javascript
var age = 0;
// bad
var hasAge = new Boolean(age);
// good
var hasAge = Boolean(age);
// good
var hasAge = !!age;
```
**[[โฌ]](#TOC)**
## <a name='naming-conventions'>Naming Conventions</a> [์๋ฌธ](https://github.com/airbnb/javascript#naming-conventions)
- ํ๋ฌธ์ ์ด๋ฆ์ ํผํ์ญ์์ค. ์ด๋ฆ์์ ์๋๋ฅผ ์ฝ์ ์ ์๋๋ก ํ์ญ์์ค.
```javascript
// bad
function q() {
// ...stuff...
}
// good
function query() {
// ..stuff..
}
```
- Object, ํจ์, ๊ทธ๋ฆฌ๊ณ ์ธ์คํด์ค๋ก๋ camelCase๋ฅผ ์ฌ์ฉํ์ญ์์ค.
```javascript
// bad
var OBJEcttsssss = {};
var this_is_my_object = {};
var this-is-my-object = {};
function c() {};
var u = new user({
name: 'Bob Parr'
});
// good
var thisIsMyObject = {};
function thisIsMyFunction() {};
var user = new User({
name: 'Bob Parr'
});
```
- Class์ ์์ฑ์์๋ PascalCase๋ฅผ ์ฌ์ฉํ์ญ์์ค.
```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'
});
```
- private ์์ฑ ์ด๋ฆ์ ๋ฐ์ค `_` ์ ์ฌ์ฉํ์ญ์์ค.
```javascript
// bad
this.__firstName__ = 'Panda';
this.firstName_ = 'Panda';
// good
this._firstName = 'Panda';
```
- `this`์ ์ฐธ์กฐ๋ฅผ ์ ์ฅํ ๋ `_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);
};
}
```
- ํจ์์ ์ด๋ฆ์ ๋ถ์ฌ์ฃผ์ญ์์ค. ์ด๊ฒ์ stack traces๋ฅผ ์ถ์ ํ๊ธฐ ์ฝ๊ฒํ๊ธฐ ๋๋ฌธ์
๋๋ค.
```javascript
// bad
var log = function(msg) {
console.log(msg);
};
// good
var log = function log(msg) {
console.log(msg);
};
```
**[[โฌ]](#TOC)**
## <a name='accessors'>Accessors</a> [์๋ฌธ](https://github.com/airbnb/javascript#accessors)
- ์์ฑ์ ์ํ ์ ๊ทผ์(Accessor) ํจ์๋ ํ์ ์์ต๋๋ค.
- ์ ๊ทผ์ ํจ์๊ฐ ํ์ํ ๊ฒฝ์ฐ `getVal()` ์ด๋ `setVal('hello')` ๋ผ๊ณ ์ฌ์ฉํฉ๋๋ค.
```javascript
// bad
dragon.age();
// good
dragon.getAge();
// bad
dragon.age(25);
// good
dragon.setAge(25);
```
- ์์ฑ์ด boolean์ ๊ฒฝ์ฐ `isVal()` ์ด๋ `hasVal()` ๋ผ๊ณ ์ฌ์ฉํฉ๋๋ค.
```javascript
// bad
if (!dragon.age()) {
return false;
}
// good
if (!dragon.hasAge()) {
return false;
}
```
- ์ผ๊ด๋๋ค๋ฉด `get()` ์ด๋ `set()` ์ด๋ผ๋ ํจ์๋ฅผ ์์ฑํด๋ ์ข์ต๋๋ค.
```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];
};
```
**[[โฌ]](#TOC)**
## <a name='constructors'>Constructors</a> [์๋ฌธ](https://github.com/airbnb/javascript#constructors)
- ์ Object์์ ํ๋กํ ํ์
์ ์ฌ์ ์ํ๋ ๊ฒ์ด ์๋๋ผ, ํ๋กํ ํ์
๊ฐ์ฒด์ ๋ฉ์๋๋ฅผ ์ถ๊ฐํด ์ฃผ์ญ์์ค. ํ๋กํ ํ์
์ ์ฌ์ ์ํ๋ฉด ์์์ด ๋ถ๊ฐ๋ฅํฉ๋๋ค. ํ๋กํ ํ์
์ ๋ฆฌ์
ํ๋๊ฒ์ผ๋ก ๋ฒ ์ด์ค ํด๋์ค๋ฅผ ์ฌ์ ์ ํ ์ ์์ต๋๋ค.
```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');
};
```
- ๋ฉ์๋์ ๋ฐํ ๊ฐ์ผ๋ก `this`๋ฅผ ๋ฐํํจ์ผ๋ก์จ ๋ฉ์๋ ์ฒด์ธ์ ํ ์ ์์ต๋๋ค.
```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);
```
- ๋
์์ ์ธ toString()์ ๋ง๋ค ์๋ ์์ง๋ง ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ๋์ง, ๋ถ์์ฉ์ด ์๋ ๊ฒ๋ง์ ํ์ธํด ์ฃผ์ญ์์ค.
```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();
};
```
**[[โฌ]](#TOC)**
## <a name='events'>Events</a>
- (DOM ์ด๋ฒคํธ๋ Backbone events์ ๊ฐ์ ๊ณ ์ ์) ์ด๋ฒคํธ ํ์ฌ์ฒด(payloads)์ ๊ฐ์ ์ ๋ฌํ๋ ๊ฒฝ์ฐ ์์ ๊ฐ(raw value) ๋์ ํด์ ์ธ์(hash)๋ฅผ ์ ๋ฌํฉ๋๋ค.
์ด๋ ๊ฒํ๋ ๊ฒ์ผ๋ก ๋์ค์ ๊ฐ๋ฐ์๊ฐ ์ด๋ฒคํธ์ ๊ด๋ จ๋ ๋ชจ๋ ํธ๋ค๋ฌ๋ฅผ ์ฐพ์ ์
๋ฐ์ดํธ ํ์ง ์๊ณ ์ด๋ฒคํธ ํ์ฌ์ฒด(payloads)์ ๊ฐ์ ์ถ๊ฐ ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ์ด๊ฒ ๋์ :
```js
// bad
$(this).trigger('listingUpdated', listing.id);
...
$(this).on('listingUpdated', function(e, listingId) {
// do something with listingId
});
```
์ด์ชฝ์ ์ ํธํฉ๋๋ค.:
```js
// good
$(this).trigger('listingUpdated', { listingId : listing.id });
...
$(this).on('listingUpdated', function(e, data) {
// do something with data.listingId
});
```
**[[โฌ]](#TOC)**
## <a name='modules'>Modules</a> [์๋ฌธ](https://github.com/airbnb/javascript#modules)
- ๋ชจ๋์ ์์์ `!` ๋ก ์์ํ์ญ์์ค. ์ด๊ฒ์ ๋ฌธ๋ง์ ์ธ๋ฏธ์ฝ๋ก ์ ๋ฃ๋๊ฒ์ ์์ ๋ชจ๋์ ์ฐ๊ฒฐํ ๋ ๋ฐํ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ง ์๊ธฐ ๋๋ฌธ์
๋๋ค.
- ํ์ผ ์ด๋ฆ์ camelCase๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ ์ด๋ฆ์ ํด๋์ ์ ์ฅํด์ฃผ์ญ์์ค. ๋ํ ๋จ๋
์ผ๋ก ๊ณต๊ฐํ ๊ฒฝ์ฐ ์ด๋ฆ์ ์ผ์น์์ผ์ฃผ์ญ์์ค.
- noConflict() ๋ผ๋ ๋ช
์นญ์ผ๋ก (์ด๋ฆ์ด ๊ฒน์ณ ๋ฎ์ด ์จ์ง๊ธฐ ์ ์) ๋ชจ๋์ ๋ฐํํ๋ ๋ฉ์๋๋ฅผ ์ถ๊ฐํด์ฃผ์ญ์์ค.
- ํญ์ ๋ชจ๋์ ์์ ๋ถ๋ถ์์` 'use strict';`๋ฅผ ์ ์ธํด์ฃผ์ญ์์ค.
```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);
```
**[[โฌ]](#TOC)**
## <a name='jquery'>jQuery</a> [์๋ฌธ](https://github.com/airbnb/javascript#jquery)
- jQuery Object์ ๋ณ์ ์์๋ `$`์ ๋ถ์ฌํด ์ฃผ์ญ์์ค.
```javascript
// bad
var sidebar = $('.sidebar');
// good
var $sidebar = $('.sidebar');
```
- jQuery ์ฟผ๋ฆฌ๊ฒฐ๊ณผ๋ฅผ ์บ์ํด์ฃผ์ญ์์ค.
```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'
});
}
```
- DOM ๊ฒ์์ Cascading `$('.sidebar ul')` ์ด๋ parent > child `$('.sidebar > ul')` ๋ฅผ ์ฌ์ฉํด์ฃผ์ญ์์ค. [jsPerf](http://jsperf.com/jquery-find-vs-context-sel/16)
- jQuery Object ๊ฒ์์ ์ค์ฝํ๊ฐ ๋ถ์ `find`๋ฅผ ์ฌ์ฉํด์ฃผ์ญ์์ค.
```javascript
// bad
$('ul', '.sidebar').hide();
// bad
$('.sidebar').find('ul').hide();
// good
$('.sidebar ul').hide();
// good
$('.sidebar > ul').hide();
// good
$sidebar.find('ul');
```
**[[โฌ]](#TOC)**
## <a name='es5'>ECMAScript 5 Compatibility</a> [์๋ฌธ](https://github.com/airbnb/javascript#es5)
- [Kangax](https://twitter.com/kangax/)์ ES5 [compatibility table](http://kangax.github.com/es5-compat-table/)๋ฅผ ์ฐธ์กฐํด ์ฃผ์ญ์์ค.
**[[โฌ]](#TOC)**
## <a name='testing'>Testing</a> [์๋ฌธ](https://github.com/airbnb/javascript#testing)
- **๋ค!(Yup.)**
```javascript
function() {
return true;
}
```
**[[โฌ]](#TOC)**
## <a name='performance'>Performance</a> [์๋ฌธ](https://github.com/airbnb/javascript#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...
**[[โฌ]](#TOC)**
## <a name='resources'>Resources</a> [์๋ฌธ](https://github.com/airbnb/javascript#resources)
**Read This**
- [Annotated ECMAScript 5.1](http://es5.github.com/)
**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/)
**Other Styles**
- [Naming this in nested functions](https://gist.github.com/4135065) - Christian Johansen
- [Conditional Callbacks](https://github.com/airbnb/javascript/issues/52)
- [Popular JavaScript Coding Conventions on Github](http://sideeffect.kr/popularconvention/#javascript)
**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
**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/)
**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)
**[[โฌ]](#TOC)**
## <a name='in-the-wild'>In the Wild</a>
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)
- **Airbnb**: [airbnb/javascript](https://github.com/airbnb/javascript)
- **American Insitutes for Research**: [AIRAST/javascript](https://github.com/AIRAST/javascript)
- **Compass Learning**: [compasslearning/javascript-style-guide](https://github.com/compasslearning/javascript-style-guide)
- **ExactTarget**: [ExactTarget/javascript](https://github.com/ExactTarget/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)
- **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)
- **National Geographic**: [natgeo/javascript](https://github.com/natgeo/javascript)
- **National Park Service**: [nationalparkservice/javascript](https://github.com/nationalparkservice/javascript)
- **Razorfish**: [razorfish/javascript-style-guide](https://github.com/razorfish/javascript-style-guide)
- **Shutterfly**: [shutterfly/javascript](https://github.com/shutterfly/javascript)
- **Userify**: [userify/javascript](https://github.com/userify/javascript)
- **Zillow**: [zillow/javascript](https://github.com/zillow/javascript)
- **ZocDoc**: [ZocDoc/javascript](https://github.com/ZocDoc/javascript)
## <a name='translation'>Translation</a>
This style guide is also available in other languages:
- :de: **German**: [timofurrer/javascript-style-guide](https://github.com/timofurrer/javascript-style-guide)
- :jp: **Japanese**: [mitsuruog/javacript-style-guide](https://github.com/mitsuruog/javacript-style-guide)
- :br: **Portuguese**: [armoucar/javascript-style-guide](https://github.com/armoucar/javascript-style-guide)
- :cn: **Chinese**: [adamlu/javascript-style-guide](https://github.com/adamlu/javascript-style-guide)
- :es: **Spanish**: [paolocarrasco/javascript-style-guide](https://github.com/paolocarrasco/javascript-style-guide)
- :kr: **Korean**: [tipjs/javascript-style-guide](https://github.com/tipjs/javascript-style-guide)
## <a name='guide-guide'>The JavaScript Style Guide Guide</a>
- [Reference](https://github.com/airbnb/javascript/wiki/The-JavaScript-Style-Guide-Guide)
## <a name='authors'>Contributors</a>
- [View Contributors](https://github.com/airbnb/javascript/graphs/contributors)
## <a name='license'>License</a>
(The MIT License)
Copyright (c) 2012 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.
**[[โฌ]](#TOC)**
# };