์๋ฐ ์คํฌ๋ฆฝํธ์ ๋ํ ๊ฐ์ฅ ํฉ๋ฆฌ์ ์ธ ์ ๊ทผ ๋ฐฉ์

๋ค๋ฅธ ์คํ์ผ ๊ฐ์ด๋๋ค
- ์ ํ(Types)
- ์ฐธ์กฐ(References)
- ๊ฐ์ฒด(Objects)
- ๋ฐฐ์ด(Arrays)
- ๊ตฌ์กฐํ ๋์ (Destructuring)
- ๋ฌธ์์ด(Strings)
- ํจ์(Functions)
- ์ ๋ก์ฐ ํจ์(Arrow Functions)
- ์์ฑ์(Constructors)
- ๋ชจ๋(Modules)
- ์ดํฐ๋ ์ดํฐ์ ์ ๋๋ ์ดํฐ(Iterators and Generators)
- ์์ฑ(Properties)
- ๋ณ์(Variables)
- ํธ์ด์คํ (Hoisting)
- ์กฐ๊ฑด์๊ณผ ๋ฑ๊ฐํ(Comparison Operators & Equality)
- ๋ธ๋ก(Blocks)
- ์ฃผ์(Comments)
- ๊ณต๋ฐฑ(Whitespace)
- ์ผํ(Commas)
- ์ธ๋ฏธ์ฝ๋ก (Semicolons)
- ํ๋ณํ๊ณผ ๊ฐ์ (Type Casting & Coercion)
- ๋ช ๋ช ๊ท์น(Naming Conventions)
- ์ก์ธ์(Accessors)
- ์ด๋ฒคํธ(Events)
- jQuery
- ECMAScript 5 ํธํ์ฑ(ECMAScript 5 Compatibility)
- ECMAScript 6 ์คํ์ผ(ECMAScript 6 Styles)
- ํ ์คํ (Testing)
- ์ฑ๋ฅ(Performance)
- ์ฐธ๊ณ (Resources)
- ๊ธฐ์ฌ(In the Wild)
- ๋ฒ์ญ(Translation)
- ์๋ฐ์คํฌ๋ฆฝํธ ์คํ์ผ ๊ฐ์ด๋ ์๋ด์(The JavaScript Style Guide Guide)
- ์๋ฐ์คํฌ๋ฆฝํธ ์คํ์ผ ๊ฐ์ด๋ ์ฑํ (Chat With Us About JavaScript)
- ์ฐธ์ฌ์(Contributors)
- ๋ผ์ด์ผ์ค(License)
-
1.1 Primitives: ์์ํ(Primitive type)์ ๊ทธ ๊ฐ์ ์ง์ ์กฐ์ํฉ๋๋ค.
stringnumberbooleannullundefined
const foo = 1; let bar = foo; bar = 9; console.log(foo, bar); // => 1, 9
-
1.2 Complex: ์ฐธ์กฐํ(Complex type)์ ์ฐธ์กฐ๋ฅผ ํตํด ๊ฐ์ ์กฐ์ํฉ๋๋ค.
objectarrayfunction
const foo = [1, 2]; const bar = foo; bar[0] = 9; console.log(foo[0], bar[0]); // => 9, 9
-
2.1 ๋ชจ๋ ์ฐธ์กฐ์๋
const๋ฅผ ์ฌ์ฉํ๊ณvar๋ฅผ ์ฌ์ฉํ์ง ์์ต๋๋ค.์์ฃ ? ์ฐธ์กฐ๋ฅผ ๋ค์ ํ ๋นํ ์ ์์ด์, ๋ฒ๊ทธ๋ก ์ฐ๊ฒฐ๋๊ฑฐ๋ ์ดํดํ๊ธฐ ์ด๋ ค์ด ์ฝ๋๊ฐ ๋๋ ๊ฒ์ ์๋ฐฉํฉ๋๋ค.
eslint rules:
prefer-const,no-const-assign.// bad var a = 1; var b = 2; // good const a = 1; const b = 2;
-
2.2 ์ฐธ์กฐ๋ฅผ ๋ค์ ํ ๋นํด์ผ ํ๋ ๊ฒฝ์ฐ
var๋์ ์let์ ์ฌ์ฉํ์ธ์.์์ฃ ?
var๋ ํจ์-๋ฒ์(function-scoped)์ด๊ณlet์ ๋ธ๋ก-๋ฒ์(block-scoped)์ด๊ธฐ ๋๋ฌธ์ ๋๋ค.eslint rules:
no-var.// bad var count = 1; if (true) { count += 1; } // good, use the let. let count = 1; if (true) { count += 1; }
-
2.3
let๊ณผconst๋ ๋ชจ๋ ๋ธ๋ก-๋ฒ์(block-scoped)์ธ ๊ฒ์ ์ฃผ์ํด์ผ ํฉ๋๋ค.// const์ let์ ์ ์ธ ๋ ๋ธ๋ก ์์์๋ง ์กด์ฌํจ. { let a = 1; const b = 1; } console.log(a); // ReferenceError console.log(b); // ReferenceError
-
3.1 ๊ฐ์ฒด๋ฅผ ๋ง๋ค ๋์๋ ๋ฆฌํฐ๋ด ๊ตฌ๋ฌธ์ ์ฌ์ฉํฉ๋๋ค.
eslint rules:
no-new-object.// bad const item = new Object(); // good const item = {};
-
3.2 ์ฝ๋๊ฐ ๋ธ๋ผ์ฐ์ ์์ ์คํ๋๋ ๊ฒฝ์ฐ ์์ฝ์ด๋ฅผ ํค๋ก ์ฌ์ฉํ์ง ๋ง์ธ์. ์ด๊ฒ์ IE8์์ ์๋ํ์ง ์์ต๋๋ค. ๋ ์์๋ณด๊ธฐ. ES6 ๋ชจ๋๊ณผ ์๋ฒ ์ฌ์ด๋์์๋ ์ฌ์ฉํ ์ ์์ต๋๋ค.
// bad const superman = { default: { clark: 'kent' }, private: true, }; // good const superman = { defaults: { clark: 'kent' }, hidden: true, };
-
3.3 ์์ฝ์ด ๋์ ์ ์๊ธฐ ์ฌ์ด ๋์์ด(Readable Synonyms)๋ฅผ ์ฌ์ฉํ์ธ์.
// bad const superman = { class: 'alien', }; // bad const superman = { klass: 'alien', }; // good const superman = { type: 'alien', };
-
3.4 ๋์ ์ธ ์์ฑ ์ด๋ฆ์ ๊ฐ์ง ๊ฐ์ฒด๋ฅผ ๋ง๋ค ๋์๋ ๊ณ์ฐ๋ ์์ฑ ์ด๋ฆ(Computed Property Names)์ ์ฌ์ฉํ์ธ์.
์์ฃ ? ์ด๋ ๊ฒํ๋ฉด ๊ฐ์ฒด ์์ฑ์ ํ ๊ฐ์ ์ฅ์์์ ์ ์ ํ ์ ์์ต๋๋ค.
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, };
-
3.5 ๋ฉ์๋์ ๋จ์ถ ๊ตฌ๋ฌธ(Object Shorthand)์ ์ฌ์ฉํ์ธ์.
eslint rules:
object-shorthand.// bad const atom = { value: 1, addValue: function (value) { return atom.value + value; }, }; // good const atom = { value: 1, addValue(value) { return atom.value + value; }, };
-
3.6 ์์ฑ์ ๋จ์ถ ๊ตฌ๋ฌธ(Object Concise)์ ์ฌ์ฉํ์ธ์.
์์ฃ ? ํํ์ด๋ ์ค๋ช ์ด ๊ฐ๊ฒฐํด์ง๊ธฐ ๋๋ฌธ์ ๋๋ค.
eslint rules:
object-shorthand.const lukeSkywalker = 'Luke Skywalker'; // bad const obj = { lukeSkywalker: lukeSkywalker, }; // good const obj = { lukeSkywalker, };
-
3.7 ์์ฑ์ ๋จ์ถ ๊ตฌ๋ฌธ(Object Concise)์ ๊ฐ์ฒด ์ ์ธ์ ์์ ๋ถ๋ถ์ ๋ฌด๋ฆฌ๋ฅผ ์ง์ด์ค๋๋ค.
์์ฃ ? ์ด๋ค ์์ฑ์ด ๋จ์ถ ๊ตฌ๋ฌธ์ ์ฌ์ฉํ๊ณ ์๋์ง๋ฅผ ์๊ธฐ๊ฐ ์ฝ๊ธฐ ๋๋ฌธ์ ๋๋ค.
const anakinSkywalker = 'Anakin Skywalker'; const lukeSkywalker = 'Luke Skywalker'; // bad const obj = { episodeOne: 1, twoJediWalkIntoACantina: 2, lukeSkywalker, episodeThree: 3, mayTheFourth: 4, anakinSkywalker, }; // good const obj = { lukeSkywalker, anakinSkywalker, episodeOne: 1, twoJediWalkIntoACantina: 2, episodeThree: 3, mayTheFourth: 4, };
-
3.8 ์์ฑ ์ด๋ฆ์ ์์ ๋ฐ์ดํ๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๋ ์ค์ง ์๋ชป๋ ์๋ณ์(Invalid Identifiers)์ผ ๋์ ๋๋ค.
์์ฃ ? ์ฃผ๊ด์ ์ผ๋ก ์ฝ๊ฒ ์ฝ์ ์ ์๋ ๊ฒ์ ํญ์ ๊ณ ๋ฏผํด์ผ ํฉ๋๋ค. ์ด ๊ฒ์ ๊ตฌ๋ฌธ์ด ๊ฐ์กฐ๋๊ณ , ์๋ง์ JS์์ง์ ์ฝ๊ฒ ์ต์ ํ๋์ด ์์ต๋๋ค.
eslint rules: quote-props.
// bad
const bad = {
'foo': 3,
'bar': 4,
'data-blah': 5,
};
// good
const good = {
foo: 3,
bar: 4,
'data-blah': 5,
};-
4.1 ๋ฐฐ์ด์ ๋ง๋ค ๋ ๋ฆฌํฐ๋ด ๊ตฌ๋ฌธ์ ์ฌ์ฉํ์ธ์.
eslint rules:
no-array-constructor.// bad const items = new Array(); // good const items = [];
-
4.2 ๋ฐฐ์ด์ ํญ๋ชฉ์ ์ง์ ๋์ฒดํ์ง ๋ง๊ณ Array#push๋ฅผ ์ฌ์ฉํ์ธ์.
const someStack = []; // bad someStack[someStack.length] = 'abracadabra'; // good someStack.push('abracadabra');
-
4.3 ๋ฐฐ์ด์ ๋ณต์ฌํ๋ ๊ฒฝ์ฐ, ๋ฐฐ์ด์ ํ์ฅ ์ฐ์ฐ์์ธ
...์ ์ฌ์ฉํ์ธ์.// bad const len = items.length; const itemsCopy = []; let i; for (i = 0; i < len; i++) { itemsCopy[i] = items[i]; } // good const itemsCopy = [...items];
-
4.4 Array-Like ๊ฐ์ฒด๋ฅผ ๋ฐฐ์ด๋ก ๋ณํํ๋ ค๋ฉด Array#from์ ์ฌ์ฉํ์ธ์.
const foo = document.querySelectorAll('.foo'); const nodes = Array.from(foo);
-
5.1 ์ฌ๋ฌ ์์ฑ์์ ๊ฐ์ฒด์ ์ ๊ทผํ ๋ ๊ฐ์ฒด ๊ตฌ์กฐํ ๋์ (Destructuring)์ ์ฌ์ฉํ์ธ์.
์์ฃ ? ๊ตฌ์กฐํ ๋์ ์ ์ด์ฉํ์ฌ ๊ทธ ์์ฑ์ ๋ํ ์ค๊ฐ ์ฐธ์กฐ๋ฅผ ์ค์ผ ์ ์์ต๋๋ค.
// bad function getFullName(user) { const firstName = user.firstName; const lastName = user.lastName; return `${firstName} ${lastName}`; } // good function getFullName(user) { const { firstName, lastName } = user; return `${firstName} ${lastName}`; } // best function getFullName({ firstName, lastName }) { return `${firstName} ${lastName}`; }
-
5.2 ๋ฐฐ์ด์ ๊ตฌ์กฐํ ๋์ (Destructuring)์ ์ฌ์ฉํ์ธ์.
const arr = [1, 2, 3, 4]; // bad const first = arr[0]; const second = arr[1]; // good const [first, second] = arr;
-
5.3 ์ฌ๋ฌ ๊ฐ์ ๋ฐํํ๋ ๊ฒฝ์ฐ, ๋ฐฐ์ด์ ๊ตฌ์กฐํ ๋์ ์ด ์๋๋ผ ๊ฐ์ฒด์ ๊ตฌ์กฐํ ๋์ ์ ์ฌ์ฉํ์ธ์.
์์ฃ ? ์ด๋ ๊ฒํ๋ฉด ๋์ค์ ์ ์์ฑ์ ์ถ๊ฐํ๊ฑฐ๋ ํธ์ถ์ ์ํฅ์ ์ฃผ์ง์๊ณ ์์๋ฅผ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
// bad function processInput(input) { // ๊ทธ๋ฌ๋ฉด ๊ธฐ์ ์ด ์ผ์ด๋๋ค return [left, right, top, bottom]; } // ํธ์ถ์์ ๋ฐํ๋๋ ๋ฐ์ดํฐ์ ์์๋ฅผ ๊ณ ๋ คํด์ผ ํจ const [left, __, top] = processInput(input); // good function processInput(input) { // ๊ทธ๋ฌ๋ฉด ๊ธฐ์ ์ด ์ผ์ด๋๋ค return { left, right, top, bottom }; } // ํธ์ถํ๋ฉด์ ํ์ํ ๋ฐ์ดํฐ๋ง ์ ํํ ์ ์์ const { left, right } = processInput(input);
-
6.1 ๋ฌธ์์ด์๋ ์์ ๋ฐ์ดํ
''๋ฅผ ์ฌ์ฉํ์ธ์.eslint rules:
quotes.// bad const name = "Capt. Janeway"; // good const name = 'Capt. Janeway';
-
6.2 100์ ์ด์์ ๋ฌธ์์ด์ ์ฌ๋ฌ ํ์ ์ฌ์ฉํ์ฌ ์ฐ๊ฒฐํ ์ ์์ต๋๋ค.
-
6.3 ์ฃผ์: ๋ฌธ์์ด ์ฐ๊ฒฐ์ด ๋ง์ผ๋ฉด ์ฑ๋ฅ์ ์ํฅ์ ์ค ์ ์์ต๋๋ค. jsPerf & Discussion.
// bad 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 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 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.';
-
6.4 ํ๋ก๊ทธ๋จ์์ ๋ฌธ์์ด์ ์์ฑํ๋ ๊ฒฝ์ฐ, ๋ฌธ์์ด ์ฐ๊ฒฐ์ด ์๋๋ผ ํ ํ๋ฆฟ ๋ฌธ์์ด(Template Strings)์ ์ฌ์ฉํ์ธ์.
์์ฃ ? ํ ํ๋ฆฟ ๋ฌธ์์ด์ ๋ฌธ์์ด ์์ฑ ๊ธฐ๋ฅ๊ณผ ๋ค์ค ๋ฌธ์์ด ๊ธฐ๋ฅ์ ๊ฐ์ง ๊ฐ๊ฒฐํ ๊ตฌ๋ฌธ์ผ๋ก ๊ฐ๋ ์ฑ์ด ์ข์์ง๊ธฐ ๋๋ฌธ์ ๋๋ค.
eslint rules:
prefer-template.// bad function sayHi(name) { return 'How are you, ' + name + '?'; } // bad function sayHi(name) { return ['How are you, ', name, '?'].join(); } // good function sayHi(name) { return `How are you, ${name}?`; }
-
6.5 ์ ๋๋ก
eval()์ ์ฌ์ฉํ์ง ์์ต๋๋ค. ์ด๊ฒ์ ์ง๊ธ๊น์ง ์๋ง์ ์ทจ์ฝ์ ์ ๋ง๋ค์ด ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
-
7.1 ํจ์ ์ ์ธ ๋์ ์ ํจ์ ํํ์์ ์ฌ์ฉํฉ๋๋ค.
์์ฃ ? ์ด๋ฆ์ด ๋ถ์ ํจ์ ์ ์ธ์ ์ฝ์คํ์์ ์ฝ๊ฒ ์์ ์์ต๋๋ค. ๋ํ ํจ์ ์ ์ธ์ ๋ชธ ์ ์ฒด๊ฐ Hoist๋ฉ๋๋ค. ๋ฐ๋ฉด ํจ์๋ ์ฐธ์กฐ๋ง Hoist๋ฉ๋๋ค. ์ด ๊ท์น์ ํจ์ ๋ถ๋ถ์ ํญ์ ์ ๋ก์ฐ ํจ์๋ก ๋์ฒด ์ฌ์ฉํ ์ ์์ต๋๋ค.
// bad const foo = function () { }; // good function foo() { }
-
7.2 ํจ์ ํํ์(Function expressions):
// ์ฆ์-ํธ์ถ(Immediately-Invoked) ํจ์ ํํ์(IIFE) (() => { console.log('Welcome to the Internet. Please follow me.'); })();
-
7.3 ํจ์ ์ด์ธ์ ๋ธ๋ก (
if๋while๋ฑ)์ ํจ์๋ฅผ ์ ์ธํ์ง ์์ต๋๋ค. ๋ธ๋ผ์ฐ์ ๋ ๋ณ์์ ํจ์๋ฅผ ํ ๋นํ๋ ์ฒ๋ฆฌ๋ฅผ ํ ์๋ ์์ง๋ง, ๋ชจ๋ ๋ค๋ฅด๊ฒ ํด์๋ฉ๋๋ค. -
7.4 ์ฃผ์: ECMA-262์์
block์ statements ๋ชฉ๋ก์ ์ ์๋์ง๋ง, ํจ์ ์ ์ธ์ statements๊ฐ ์์ต๋๋ค. ์ด ๋ฌธ์ ๋ ECMA-262์ ์ค๋ช ์ ์ฐธ์กฐํ์ธ์.// bad if (currentUser) { function test() { console.log('Nope.'); } } // good let test; if (currentUser) { test = () => { console.log('Yup.'); }; }
-
7.5 ๋งค๊ฐ๋ณ์(parameter)์
arguments๋ฅผ ์ ๋๋ก ์ง์ ํ์ง ์์ต๋๋ค. ์ด๊ฒ์ ํจ์ ์์ญ์ผ๋ก ์ ๋ฌ ๋arguments๊ฐ์ฒด์ ์ฐธ์กฐ๋ฅผ ๋ฎ์ด ์จ๋ฒ๋ฆด ๊ฒ์ ๋๋ค.// bad function nope(name, options, arguments) { // ...stuff... } // good function yup(name, options, args) { // ...stuff... }
-
7.6
arguments๋ฅผ ์ฌ์ฉํ์ง ์์ต๋๋ค. ๋์ ๋ ์คํธ(Rest) ๋ฌธ๋ฒ์ธ...์ ์ฌ์ฉํ์ธ์.์์ฃ ?
...๋ฅผ ์ด์ฉํ์ฌ ์ฌ๋ฌ๊ฐ์ง ๋งค๊ฐ๋ณ์๋ฅผ ๋ชจ๋ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ถ๊ฐ๋ก rest ๋งค๊ฐ๋ณ์์ธarguments๋ Array-Like ๊ฐ์ฒด๊ฐ ์๋๋ผ ์ง์ ํ ๋ฐฐ์ด(Array)์ ๋๋ค.// bad function concatenateAll() { const args = Array.prototype.slice.call(arguments); return args.join(''); } // good function concatenateAll(...args) { return args.join(''); }
-
7.7 ํจ์์ ๋งค๊ฐ๋ณ์๋ฅผ ์กฐ์ํ์ง ๋ง๊ณ ๊ธฐ๋ณธ ๋งค๊ฐ๋ณ์(Default Parameters)๋ฅผ ์ฌ์ฉํ์ธ์.
// really bad function handleThings(opts) { // ์๋! ํจ์์ ๋งค๊ฐ๋ณ์๋ฅผ ์กฐ์ํ์ง ์์ต๋๋ค. // ๋ง์ฝ opts๊ฐ falsy ์ธ ๊ฒฝ์ฐ๋ ๋ฐ๋๋๋ก ๊ฐ์ฒด๊ฐ ์ค์ ๋ฉ๋๋ค. // ๊ทธ๋ฌ๋ ๋ฏธ๋ฌํ ๋ฒ๊ทธ๋ฅผ ์ผ์ผํค๋ ์์ธ์ด ๋ ์๋ ์์ต๋๋ค. opts = opts || {}; // ... } // still bad function handleThings(opts) { if (opts === void 0) { opts = {}; } // ... } // good function handleThings(opts = {}) { // ... }
-
7.8 ๋ถ์์ฉ์ด ์๋ ๊ธฐ๋ณธ ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ์ง ์์ต๋๋ค.
์์ฃ ? ํผ๋์ค๋ฝ๊ธฐ ๋๋ฌธ์ ๋๋ค.
var b = 1; // bad function count(a = b++) { console.log(a); } count(); // 1 count(); // 2 count(3); // 3 count(); // 3
-
7.9 ํญ์ ๊ธฐ๋ณธ ๋งค๊ฐ๋ณ์๋ ์์ชฝ์ ๋ฐฐ์นํ์ธ์.
// bad function handleThings(opts = {}, name) { // ... } // good function handleThings(name, opts = {}) { // ... }
-
7.10 ์๋ก์ด ํจ์๋ฅผ ๋ง๋๋ ๋ฐ Function ์์ฑ์๋ฅผ ์ฌ์ฉํ์ง ์์ต๋๋ค.
์์ฃ ? ์ด ๋ฐฉ๋ฒ์ ๋ฌธ์์ด์ ๊ตฌ๋ถํ๋ ์๋ก์ด ํจ์๋ฅผ ๋ง๋ค ์ ์๋ eval()๊ณผ ๊ฐ์ ์ทจ์ฝ์ ์ด ๋ฐ์ํ ์ ์์ต๋๋ค.
// bad var add = new Function('a', 'b', 'return a + b'); // still bad var subtract = Function('a', 'b', 'return a - b');
-
7.11 ํจ์์ ์ฌ์ฉ๋๋ ๊ณต๋ฐฑ
์์ฃ ? ์ผ๊ด์ฑ์ด ์ข๊ณ , ํจ์์ด๋ฆ์ ์ถ๊ฐ ํ๊ฑฐ๋ ์ญ์ ํ ๋ ๊ณต๋ฐฑ์ ์ ๊ฑฐํ ํ์๊ฐ ์์ต๋๋ค.
// bad const f = function(){}; const g = function (){}; const h = function() {}; // good const x = function () {}; const y = function a() {};
-
7.12 ์ ๋๋ก ๋งค๊ฐ๋ณ์๋ฅผ ์กฐ์ํ์ง ์์ต๋๋ค.
์์ฃ ? ๋งค๊ฐ๋ณ์๋ก ์ ๋ฌ ๋ ๊ฐ์ฒด๋ฅผ ์กฐ์ํ๋ ๊ฒ์ ์๋์ ํธ์ถ์ ์์น ์๋ ๋ณ์ ๋ถ์์ฉ์ ์ผ์ผํฌ ์ ์์ต๋๋ค.
eslint rules:
no-param-reassign.// bad function f1(obj) { obj.key = 1; }; // good function f2(obj) { const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1; };
-
7.13 ์ ๋๋ก ๋งค๊ฐ๋ณ์๋ฅผ ๋ค์ ์ง์ ํ์ง ์์ต๋๋ค.
์์ฃ ?
arguments๊ฐ์ฒด์ ์ ๊ทผํ๋ ๊ฒฝ์ฐ ๋ค์ ์ง์ ๋ ๋งค๊ฐ๋ณ์๋ ์๊ธฐ์น ์์ ๋์์ด ๋ฐ์ํ ์ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ํนํ V8 ์ต์ ํ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.eslint rules:
no-param-reassign.// bad function f1(a) { a = 1; } function f2(a) { if (!a) { a = 1; } } // good function f3(a) { const b = a || 1; } function f4(a = 1) { }
-
8.1 ํจ์ ํํ์์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ(์ต๋ช ํจ์์ ๊ฐ์), ์ ๋ก์ฐ ํจ์(Arrow Functions)๋ฅผ ์ฌ์ฉํ์ธ์.
์์ฃ ? ์ ๋ก์ฐ ํจ์๋ ํจ์๊ฐ ์คํ๋๋ ์ปจํ ์คํธ์
this๋ฅผ ๊ฐ๋์ด์ค๋๋ค. ์ด๊ฒ์ ๋๋ฌด๋ ์ํ๋ ๊ฒ์ด๋ฉฐ ๊ตฌ๋ฌธ๋ ๋์ฑ ๊ฐ๊ฒฐํด์ง๋๋ค.์ธ์ ์ฐ์ฃ ? ๋ณต์กํ ํจ์ ๋ ผ๋ฆฌ๋ฅผ ์ ์ํ ํจ์์ ๋ฐ๊นฅ์ชฝ์ผ๋ก ์ด๋ํ๊ณ ์ถ์ ๊ฒฝ์ฐ์ ๋๋ค.
eslint rules:
prefer-arrow-callback,arrow-spacing.// bad [1, 2, 3].map(function (x) { const y = x + 1; return x * y; }); // good [1, 2, 3].map((x) => { const y = x + 1; return x * y; });
-
8.2 ํจ์์ ๋ณธ์ฒด๊ฐ ํ๋์ ํํ์์ผ๋ก ๊ตฌ์ฑ๋์ด์๋ ๊ฒฝ์ฐ ์ค๊ดํธ
{}๋ฅผ ์๋ตํ๊ณ ์๋ฌต์ return์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉดreturn๋ฌธ์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.์์ฃ ? ๊ฐ๋ ์ฑ์ด ์ข์์ง๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ฌ๋ฌ ํจ์๊ฐ ์ฐ๊ฒฐ๋๋ ๊ฒฝ์ฐ์ ์ฝ๊ฒ ์ฝ์ ์ ์์ต๋๋ค.
์ธ์ ์ฐ์ฃ ? ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ ๊ฒฝ์ฐ.
eslint rules:
arrow-parens,arrow-body-style.// good [1, 2, 3].map(number => `A string containing the ${number}.`); // bad [1, 2, 3].map(number => { const nextNumber = number + 1; `A string containing the ${nextNumber}.`; }); // good [1, 2, 3].map(number => { const nextNumber = number + 1; return `A string containing the ${nextNumber}.`; });
-
8.3 ๊ตฌ๋ฌธ์ ๊ธธ์ด๊ฐ ์ฌ๋ฌ ํ์ ๊ฑธ์น๋ ๊ฒฝ์ฐ ๊ฐ๋ ์ฑ์ ํฅ์์ํค๊ธฐ ์ํด ๊ดํธ
()์์ ์จ์ฃผ์ธ์.์์ฃ ? ํจ์์ ์์๊ณผ ๋ ๋ถ๋ถ์ ์์๋ณด๊ธฐ ์ฝ๊ฒ ํฉ๋๋ค.
// bad [1, 2, 3].map(number => 'As time went by, the string containing the ' + `${number} became much longer. So we needed to break it over multiple ` + 'lines.' ); // good [1, 2, 3].map(number => ( `As time went by, the string containing the ${number} became much ` + 'longer. So we needed to break it over multiple lines.' ));
-
8.4 ํจ์์ ์ธ์๊ฐ ํ ๊ฐ์ธ ๊ฒฝ์ฐ ๊ดํธ
()๋ฅผ ์๋ตํ ์ ์์ต๋๋ค.์์ฃ ? ์๊ฐ์ ํผ๋์ด ๋ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
eslint rules:
arrow-parens.// bad [1, 2, 3].map((x) => x * x); // good [1, 2, 3].map(x => x * x); // good [1, 2, 3].map(number => ( `A long string with the ${number}. Itโs so long that weโve broken it ` + 'over multiple lines!' )); // bad [1, 2, 3].map(x => { const y = x + 1; return x * y; }); // good [1, 2, 3].map((x) => { const y = x + 1; return x * y; });
-
9.1
prototype์ ์ง์ ์กฐ์์ ํผํ๊ณ ํญ์class๋ฅผ ์ฌ์ฉํ์ธ์.์์ฃ ?
class๊ตฌ๋ฌธ์ ๊ฐ๊ฒฐํ๊ณ ์๋๋ฅผ ์์๋ด๊ธฐ๊ฐ ์ฝ๊ธฐ ๋๋ฌธ์ ๋๋ค.// 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; } }
-
9.2 ์์์
extends๋ฅผ ์ฌ์ฉํ์ธ์.์์ฃ ? ํ๋กํ ํ์ ์ ์์ํ๊ธฐ ์ํด ๋ด์ฅ๋ ๋ฐฉ์์ผ๋ก
instanceof๋ฅผ ํ๊ดดํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.// 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]; } }
-
9.3 ๋ฉ์๋์ ๋ฐํ ๊ฐ์
this๋ฅผ ๋๋ ค์ฃผ๋ ๊ฒ์ผ๋ก, ๋ฉ์๋ ์ฒด์ธ์ ํ ์ ์์ต๋๋ค.// 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);
-
9.4 ์ฌ์ฉ์ํ ๋ toString() ๋ฉ์๋๋ฅผ ์ฐ๋ ๊ฒ๋ ์ข์ต๋๋ค. ๋จ, ์ ๋๋ก ์๋ํ๋์ง, ๋ถ์์ฉ์ด ์๋ ์ง๋ฅผ ๊ผญ ํ์ธํ์ธ์.
class Jedi { constructor(options = {}) { this.name = options.name || 'no name'; } getName() { return this.name; } toString() { return `Jedi - ${this.getName()}`; } }
-
10.1 ๋นํ์ค ๋ชจ๋ ์์คํ ์ด ์๋๋ผ๋ฉด ํญ์ (
import/export) ๋ฅผ ์ฌ์ฉํ์ธ์. ์ด๋ ๊ฒ ํจ์ผ๋ก์จ ์ํ๋ ๋ชจ๋ ์์คํ ์ ์ธ์ ๋ ์ง ํธ๋์คํ์ผ(Transpile) ํ ์ ์์ต๋๋ค.์์ฃ ? ๋ชจ๋์ ๊ณง ๋ฏธ๋์ ๋๋ค. ๋ฏธ๋๋ฅผ ์ ์ ํ๊ณ ์ ์ฉํฉ์๋ค.
// 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;
-
10.2 ์์ผ๋์นด๋๋ฅผ ์ด์ฉํ ๊ฐ์ ธ์ค๊ธฐ๋ ์ฌ์ฉํ์ง ์์ต๋๋ค.
์์ฃ ? single default export์ธ ๊ฒ์ ์ฃผ์ํ ํ์๊ฐ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
// bad import * as AirbnbStyleGuide from './AirbnbStyleGuide'; // good import AirbnbStyleGuide from './AirbnbStyleGuide';
-
10.3 import ๋ฌธ์์ ์ง์ ์ถ์ถ(Export)ํ์ง ์์ต๋๋ค.
์์ฃ ? ํ๊ฐ์ ๋ผ์ธ์ด๋ผ ๊ฐ๊ฒฐํ๊ธฐ๋ ํ์ง๋ง, import์ exportํ๋ ๋ฐฉ๋ฒ์ ๋ช ํํ๊ฒ ๊ตฌ๋ถํจ์ผ๋ก์จ ์ผ๊ด์ฑ์ ์ ์งํ ์ ์์ต๋๋ค.
// bad // filename es6.js export { es6 as default } from './airbnbStyleGuide'; // good // filename es6.js import { es6 } from './AirbnbStyleGuide'; export default es6;
-
11.1 ์ดํฐ๋ ์ดํฐ(Iterators)๋ฅผ ์ฌ์ฉํ์ง ์์ต๋๋ค.
for-of๋ฃจํ ๋์map()๊ณผreduce()๊ฐ์ ์๋ฐ์คํฌ๋ฆฝํธ์ ๊ณ ๊ธํจ์(higher-order functions)๋ฅผ ์ฌ์ฉํ์ธ์.์์ฃ ? ์ด๊ฒ์ ๋ถ๋ณ(Immutable)์ ๊ท์น์ ์ ์ฉํฉ๋๋ค. ๊ฐ์ ๋ฐํํ๋ ํจ์๋ฅผ ์ฒ๋ฆฌํ๋ ๊ฒ์ด ๋ถ์์ฉ์ ์์ธกํ๊ธฐ๊ฐ ๋ ์ฝ์ต๋๋ค.
eslint rules:
no-iterator.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;
-
11.2 ํ์ฌ ์ ๋๋ ์ดํฐ(Generators)๋ ์ฌ์ฉํ์ง ์๋ ๊ฒ์ด ์ข์ต๋๋ค.
์์ฃ ? ES5์์ ํธ๋์คํ์ผ(Transpile)์ด ์ฌ๋ฐ๋ก ์๋ํ์ง ์์ต๋๋ค.
-
12.1 ์์ฑ์ ์ ๊ทผํ๋ ค๋ฉด ์
.์ ์ฌ์ฉํ์ธ์.eslint rules:
dot-notation.const luke = { jedi: true, age: 28, }; // bad const isJedi = luke['jedi']; // good const isJedi = luke.jedi;
-
12.2 ๋ณ์๋ฅผ ์ฌ์ฉํ์ฌ ์์ฑ์ ์ ๊ทผํ๋ ค๋ฉด ๋๊ดํธ
[]๋ฅผ ์ฌ์ฉํ์ธ์.const luke = { jedi: true, age: 28, }; function getProp(prop) { return luke[prop]; } const isJedi = getProp('jedi');
-
13.1 ๋ณ์๋ฅผ ์ ์ธ ํ ๋๋ ํญ์
const๋ฅผ ์ฌ์ฉํ์ธ์. ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ ์ ์ญ ๋ณ์๋ก ์ ์ธ๋ฉ๋๋ค. ๊ธ๋ก๋ฒ ๋ค์ ์คํ์ด์ค๊ฐ ์ค์ผ๋์ง ์๋๋ก ์บกํด ํ๋๋(์ญ์์ฃผ: ํ๊ฒฝ๋ณดํธ์ ์ํ๋ฅผ ํ ๋ง๋ก ํ ์ํผํ์ด๋ก ์ ๋๋ฉ์ด์ )๋ ๊ฒฝ๊ณ ํ๊ณ ์์ต๋๋ค.// bad superPower = new SuperPower(); // good const superPower = new SuperPower();
-
13.2 ํ๋์ ๋ณ์ ์ ์ธ์ ๋ํด ํ๋์
const๋ฅผ ์ฌ์ฉํ์ธ์.์์ฃ ? ์ด ๋ฐฉ๋ฒ์ ์๋ก์ด ๋ณ์๋ฅผ ์ฝ๊ฒ ์ถ๊ฐํ ์ ์์ต๋๋ค. ๋ํ ๊ตฌ๋ถ ๊ธฐํธ์ ์ฐจ์ด์ ์ํ
;์,๋ก ๋ค์๊ธ ๋์ฒดํ๋ ์์ ์ ๋ํด ์ ๊ฒฝ์ธ ํ์๊ฐ ์์ต๋๋ค.eslint rules:
one-var.// bad const items = getItems(), goSportsTeam = true, dragonball = 'z'; // bad // (compare to above, and try to spot the mistake) const items = getItems(), goSportsTeam = true; dragonball = 'z'; // good const items = getItems(); const goSportsTeam = true; const dragonball = 'z';
-
13.3 ๋จผ์
const๋ฅผ ๊ทธ๋ฃนํํ๊ณ ๊ทธ ๋ค์์ผ๋กlet์ ๊ทธ๋ฃนํ ํ์ธ์.์์ฃ ? ์ด์ ์ ํ ๋น ๋ ๋ณ์์ ๋ฐ๋ผ ๋์ค์ ์๋ก์ด ๋ณ์๋ฅผ ์ถ๊ฐํ๋ ๊ฒฝ์ฐ์ ์ ์ฉํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
// bad let i, len, dragonball, items = getItems(), goSportsTeam = true; // bad let i; const items = getItems(); let dragonball; const goSportsTeam = true; let len; // good const goSportsTeam = true; const items = getItems(); let dragonball; let i; let length;
-
13.4 ๋ณ์๋ฅผ ํ ๋น์ ํ์๋ก ํ๋ ๋ถ๋ถ์์ ์ ๋นํ ์ฅ์์ ๋ฐฐ์นํด์ผ ํฉ๋๋ค.
์์ฃ ?
let๊ณผconst๋ ํจ์ ๋ฒ์์๋ ์๋ ๋ธ๋ก ๋ฒ์์ด๊ธฐ ๋๋ฌธ์ ๋๋ค.// good function () { test(); console.log('doing stuff..'); //..other stuff.. const name = getName(); if (name === 'test') { return false; } return name; } // bad - unnecessary function call function (hasName) { const name = getName(); if (!hasName) { return false; } this.setFirstName(name); return true; } // good function (hasName) { if (!hasName) { return false; } const name = getName(); this.setFirstName(name); return true; }
-
14.1
var์ ์ธ์ ํ ๋น์ด ์๋ ์ํ๋ก ๋ฒ์(Scope)์ ์๋ก Hoist๋ ์ ์์ต๋๋ค. ํ์ง๋งconst์let์ ์ธ์ ์๊ฐ์ ๋ฐ๋ ์กด(Temporal Dead Zones (TDZ))์ด๋ผ๋ ์๋ก์ด ๊ฐ๋ ์ ํํ์ ๋ฐ๊ณ ์์ต๋๋ค. ์ด๊ฒ์ ์ typeof๊ฐ ์์ ํ์ง ์์๊ฐ(typeof is no longer safe)๋ฅผ ์๊ณ ์๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.// (notDefined๊ฐ ๊ธ๋ก๋ฒ ๋ณ์์ ์กด์ฌํ์ง ์๋๋ค๊ณ ๊ฐ์ ํ์ ๊ฒฝ์ฐ) // ์ด๊ฒ์ ์ ์๋ํ์ง ์์ต๋๋ค. function example() { console.log(notDefined); // => throws a ReferenceError } // ๋ณ์๋ฅผ ์ฐธ์กฐํ๋ ์ฝ๋ ํ์ ๊ทธ ๋ณ์๋ฅผ ์ ์ธํ ๊ฒฝ์ฐ // ๋ณ์๊ฐ Hoist๋์ด์ ์๋ํฉ๋๋ค. // ์ฃผ์: `true` ๊ฐ ์์ฒด๋ Hoistํ ์ ์์ต๋๋ค. function example() { console.log(declaredButNotAssigned); // => undefined var declaredButNotAssigned = true; } // ์ธํฐํ๋ฆฐํฐ๋ ๋ณ์ ์ ์ธ์ ๋ฒ์(Scope)์ ์์๋ถ๋ถ์ Hoistํฉ๋๋ค. // ์์ ์๋ ๋ค์๊ณผ ๊ฐ์ด ๋ค์ ์์ฑํ ์ ์์ต๋๋ค: function example() { let declaredButNotAssigned; console.log(declaredButNotAssigned); // => undefined declaredButNotAssigned = true; } // const์ let์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ function example() { console.log(declaredButNotAssigned); // => throws a ReferenceError console.log(typeof declaredButNotAssigned); // => throws a ReferenceError const declaredButNotAssigned = true; }
-
14.2 ์ต๋ช ํจ์ ํํ์์์๋ ํจ์๊ฐ ํ ๋น๋๊ธฐ ์ ์ ๋ณ์๊ฐ Hoist๋ ์ ์์ต๋๋ค.
function example() { console.log(anonymous); // => undefined anonymous(); // => TypeError anonymous is not a function var anonymous = function () { console.log('anonymous function expression'); }; }
-
14.3 ๋ช ๋ช ๋ ํจ์์ ๊ฒฝ์ฐ๋ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ณ์๊ฐ 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'); } }
-
14.4 ํจ์ ์ ์ธ์ ํจ์์ด๋ฆ๊ณผ ํจ์๋ณธ๋ฌธ์ด Hoist๋ฉ๋๋ค.
function example() { superPower(); // => Flying function superPower() { console.log('Flying'); } }
-
๋ ์์ธํ ์ ๋ณด๋ Ben Cherry์ JavaScript Scoping & Hoisting์ ์ฐธ์กฐํ์ธ์.
-
15.1
==์!=๋ณด๋ค๋===์!==๋ฅผ ์ฌ์ฉํ์ธ์. -
15.2
if์ ๊ฐ์ ์กฐ๊ฑด๋ฌธ์ToBoolean๋ฐฉ๋ฒ์ ์ํ ๊ฐ์ ํ(Type) ๋ณํ์ผ๋ก ๊ตฌ๋ถ๋๊ณ ํญ์ ๋ค์๊ณผ ๊ฐ์ ๊ฐ๋จํ ๊ท์น์ ๋ฐ๋ฆ ๋๋ค:eslint rules:
eqeqeq.- Objects๋ true๋ก ๊ตฌ๋ถ๋ฉ๋๋ค.
- Undefined๋ false๋ก ๊ตฌ๋ถ๋ฉ๋๋ค.
- Null์ false๋ก ๊ตฌ๋ถ๋ฉ๋๋ค.
- Booleans์ booleanํ์ ๊ฐ์ผ๋ก ๊ตฌ๋ถ๋ฉ๋๋ค.
- Numbers๋ true๋ก ๊ตฌ๋ถ๋ฉ๋๋ค. ๊ทธ๋ฌ๋, +0, -0, ๋๋ NaN์ธ ๊ฒฝ์ฐ false๋ก ๊ตฌ๋ถ๋ฉ๋๋ค.
- Strings๋ true๋ก ๊ตฌ๋ถ๋ฉ๋๋ค. ๊ทธ๋ฌ๋, ๋น์ด์๋
''๊ฒฝ์ฐ๋ false๋ก ๊ตฌ๋ถ๋ฉ๋๋ค.
if ([0]) { // true // ๋ฐฐ์ด์ ๊ฐ์ฒด์ด๋ฏ๋ก true๋ก ๊ตฌ๋ถ๋ฉ๋๋ค. }
-
15.3 ์์ฌ์ด ๋ฐฉ๋ฒ์ ์ฌ์ฉํ์ธ์.
// bad if (name !== '') { // ...stuff... } // good if (name) { // ...stuff... } // bad if (collection.length > 0) { // ...stuff... } // good if (collection.length) { // ...stuff... }
-
15.4 ๋ ์์ธํ ๋ด์ฉ์ ์ฌ๊ธฐ๋ฅผ ์ฐธ์กฐํ์ธ์. Truth Equality and JavaScript by Angus Croll.
-
16.1 ์ฌ๋ฌ ์ค์ ๋ธ๋ก์ ์ค๊ดํธ
{}๋ฅผ ์ฌ์ฉํฉ๋๋ค.// bad if (test) return false; // good if (test) return false; // good if (test) { return false; } // bad function () { return false; } // good function () { return false; }
-
16.2 ์ฌ๋ฌ ๋ธ๋ก์ ๊ฑธ์น
if์else๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ,else๋if๋ธ๋ก์ ๋ ์ค๊ดํธ{}์ ๊ฐ์ ํ์ ๋์ธ์.eslint rules:
brace-style.// bad if (test) { thing1(); thing2(); } else { thing3(); } // good if (test) { thing1(); thing2(); } else { thing3(); }
-
17.1 ์ฌ๋ฌ ์ค์ ์ฃผ์์๋
/** ... */๋ฅผ ์ฌ์ฉํ์ธ์. ๊ทธ ์์๋ ์ค๋ช ๊ณผ ๋ชจ๋ ๋งค๊ฐ๋ณ์์ ๋ฐํ ๊ฐ์ ๋ํ ํ์๊ณผ ๊ฐ์ ํ๊ธฐํฉ๋๋ค.// 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; }
-
17.2 ํ ์ค ์ฃผ์์๋
//๋ฅผ ์ฌ์ฉํ์ธ์. ์ฃผ์์ ์ถ๊ฐํ์ถ์ ์ฝ๋์ ์๋จ์ ๋ฐฐ์นํ์ธ์. ๋ํ ์ฃผ์ ์์ ๋น ์ค์ ๋ฃ์ด์ฃผ์ธ์.// bad const active = true; // is current tab // good // is current tab const active = true; // bad function getType() { console.log('fetching type...'); // set the default type to 'no type' const type = this._type || 'no type'; return type; } // good function getType() { console.log('fetching type...'); // set the default type to 'no type' const type = this._type || 'no type'; return type; } // also good function getType() { // set the default type to 'no type' const type = this._type || 'no type'; return type; }
-
17.3 ๋ฌธ์ ๋ฅผ ์ง์ ํ๊ณ ์ฌ๊ณ ๋ฅผ ์ด๊ตฌํ๊ฑฐ๋ ๋ฌธ์ ์ ํด๊ฒฐ์ฑ ์ ์ ์ํ๋ ๊ฒฝ์ฐ ๋ฑ, ์ฃผ์ ์์
FIXME๋๋TODO๋ฅผ ๋ถ์ด๋ ๊ฒ์ผ๋ก ๋ค๋ฅธ ๊ฐ๋ฐ์์ ๋น ๋ฅธ ์ดํด๋ฅผ ๋์ธ ์ ์์ต๋๋ค. ์ด๋ค์ ์ด๋ ํ ์ก์ ์ ๋ฐ๋ฅธ๋ค๋ ์๋ฏธ์์ ์ผ๋ฐ ๋๊ธ๊ณผ ๋ค๋ฅผ ์ ์์ต๋๋ค. ์ก์ ์FIXME -- ํด๊ฒฐ์ฑ ํ์๋๋TODO -- ๊ตฌํ ํ์. -
17.4 ๋ฌธ์ ์ ๋ํ ์ฃผ์์ผ๋ก
// FIXME:๋ฅผ ์ฌ์ฉํ์ธ์.class Calculator extends Abacus { constructor() { super(); // FIXME: shouldn't use a global here total = 0; } }
-
17.5 ํด๊ฒฐ์ฑ ์ ๋ํ ์ฃผ์์ผ๋ก
// TODO:๋ฅผ ์ฌ์ฉํ์ธ์.class Calculator extends Abacus { constructor() { super(); // TODO: total should be configurable by an options param this.total = 0; } }
-
18.1 ํญ์ ๊ณต๋ฐฑ 2๊ฐ๋ฅผ ์ค์ ํ์ธ์.
eslint rules:
indent.// bad function () { โโโโconst name; } // bad function () { โconst name; } // good function () { โโconst name; }
-
18.2 ์ค๊ดํธ
{}์์ ๊ณต๋ฐฑ์ ๋ฃ์ด์ฃผ์ธ์.eslint rules:
space-before-blocks.// 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', });
-
18.3 ์ ์ด ๊ตฌ๋ฌธ(
if,while๋ฑ)์ ๊ดํธ()์์ ๊ณต๋ฐฑ์ ๋ฃ์ด์ฃผ์ธ์. ํจ์ ์ ์ธ๊ณผ ํจ์ ํธ์ถ์ ์ธ์ ๋ชฉ๋ก ์์๋ ๊ณต๋ฐฑ์ ๋ฃ์ง ์์ต๋๋ค.eslint rules:
space-after-keywords,space-before-keywords.// bad if(isJedi) { fight (); } // good if (isJedi) { fight(); } // bad function fight () { console.log ('Swooosh!'); } // good function fight() { console.log('Swooosh!'); }
-
18.4 ์ฐ์ฐ์ ์ฌ์ด์๋ ๊ณต๋ฐฑ์ด ์์ต๋๋ค.
eslint rules:
space-infix-ops.// bad const x=y+5; // good const x = y + 5;
-
18.5 ํ์ผ์ ๋ง์ง๋ง์ ๋น ์ค์ ํ๋ ๋ฃ์ด์ฃผ์ธ์.
// bad (function (global) { // ...stuff... })(this);
// bad (function (global) { // ...stuff... })(this);โต โต
// good (function (global) { // ...stuff... })(this);โต
-
18.6 ๋ฉ์๋ ์ฒด์ธ์ด ๊ธธ์ด์ง๋ ๊ฒฝ์ฐ ์ ์ ํ ๋ค์ฌ์ฐ๊ธฐ(indentation) ํ์ธ์. ํ์ด ๋ฉ์๋ ํธ์ถ์ด ์๋ ์๋ก์ด ๋ฌธ์ฅ์์ ๊ฐ์กฐํ๊ธฐ ์ํด ์ ๋์ ์
.์ ๋ฐฐ์นํ์ธ์.// 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 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 const 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);
-
18.7 ๋ธ๋ก๊ณผ ๋ค์ Statement ์ฌ์ด์ ๋น ์ค์ ๋ฃ์ด์ฃผ์ธ์.
// bad if (foo) { return bar; } return baz; // good if (foo) { return bar; } return baz; // bad const obj = { foo() { }, bar() { }, }; return obj; // good const obj = { foo() { }, bar() { }, }; return obj; // bad const arr = [ function foo() { }, function bar() { }, ]; return arr; // good const arr = [ function foo() { }, function bar() { }, ]; return arr;
-
18.8 ๋ธ๋ก์ ๋น ์ค์ ๋ผ์๋ฃ์ง ์์ต๋๋ค.
eslint rules:
padded-blocks.// bad function bar() { console.log(foo); } // also bad if (baz) { console.log(qux); } else { console.log(foo); } // good function bar() { console.log(foo); } // good if (baz) { console.log(qux); } else { console.log(foo); }
-
18.9 ๊ดํธ
()์์ ๊ณต๋ฐฑ์ ์ถ๊ฐํ์ง ์์ต๋๋ค.eslint rules:
space-in-parens.// bad function bar( foo ) { return foo; } // good function bar(foo) { return foo; } // bad if ( foo ) { console.log(foo); } // good if (foo) { console.log(foo); }
-
18.10 ๋๊ดํธ
[]์์ ๊ณต๋ฐฑ์ ์ถ๊ฐํ์ง ์์ต๋๋ค.eslint rules:
array-bracket-spacing.// bad const foo = [ 1, 2, 3 ]; console.log(foo[ 0 ]); // good const foo = [1, 2, 3]; console.log(foo[0]);
-
18.11 ์ค๊ดํธ
{}์์ ๊ณต๋ฐฑ์ ์ถ๊ฐํ์ง ์์ต๋๋ค.eslint rules:
object-curly-spacing.// bad const foo = {clark: 'kent'}; // good const foo = { clark: 'kent' };
-
18.12 ํ ์ค์ 100๋ฌธ์(๊ณต๋ฐฑ ํฌํจ)๊ฐ ๋๋ ์ฝ๋๋ ํผํ์ธ์.
์์ฃ ? ๊ฐ๋ ์ฑ๊ณผ ์ ์ง ๋ณด์์ฑ์ ๋ณด์ฅํฉ๋๋ค.
eslint rules:
max-len.// bad const foo = 'Whatever national crop flips the window. The cartoon reverts within the screw. Whatever wizard constrains a helpful ally. The counterpart ascends!'; // bad $.ajax({ method: 'POST', url: 'https://airbnb.com/', data: { name: 'John' } }).done(() => console.log('Congratulations!')).fail(() => console.log('You have failed this city.')); // good const foo = 'Whatever national crop flips the window. The cartoon reverts within the screw. ' + 'Whatever wizard constrains a helpful ally. The counterpart ascends!'; // good $.ajax({ method: 'POST', url: 'https://airbnb.com/', data: { name: 'John' }, }) .done(() => console.log('Congratulations!')) .fail(() => console.log('You have failed this city.'));
-
19.1 ์ผํ๋ก ์์: ์ ๋ฐ ๊ทธ๋งํ์ธ์.
eslint rules:
comma-style.// bad const story = [ once , upon , aTime ]; // good const story = [ once, upon, aTime, ]; // bad const hero = { firstName: 'Ada' , lastName: 'Lovelace' , birthYear: 1815 , superPower: 'computers' }; // good const hero = { firstName: 'Ada', lastName: 'Lovelace', birthYear: 1815, superPower: 'computers', };
-
19.2 ๋ง์ง๋ง์ ์ผํ: ์ข์ต๋๋ค.
eslint rules:
comma-dangle.์์ฃ ? ์ด๊ฒ์ git์ diff๋ฅผ ๊นจ๋ํ๊ฒ ํฉ๋๋ค. ๋ํ Babel๊ณผ ๊ฐ์ ํธ๋์ค ์ปดํ์ผ๋ฌ๋ ๋์ ๋ถํ์ํ ์ผํ๋ฅผ ์์์ ์ ๊ฑฐํฉ๋๋ค. ์ด๊ฒ์ ๊ธฐ์กด ๋ธ๋ผ์ฐ์ ์์ ๋ถํ์ํ ์ผํ ๋ฌธ์ ๋ฅผ ๊ฑฑ์ ํ ํ์๊ฐ ์๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
// bad - git diff without trailing comma const hero = { firstName: 'Florence', - lastName: 'Nightingale' + lastName: 'Nightingale', + inventorOf: ['coxcomb graph', 'modern nursing'] }; // good - git diff with trailing comma const hero = { firstName: 'Florence', lastName: 'Nightingale', + inventorOf: ['coxcomb chart', 'modern nursing'], }; // bad const hero = { firstName: 'Dana', lastName: 'Scully' }; const heroes = [ 'Batman', 'Superman' ]; // good const hero = { firstName: 'Dana', lastName: 'Scully', }; const heroes = [ 'Batman', 'Superman', ];
-
20.1 ๋ฌผ๋ก ์ฌ์ฉํฉ์๋ค.
eslint rules:
semi.// bad (function () { const name = 'Skywalker' return name })() // good (() => { const name = 'Skywalker'; return name; })(); // good (guards against the function becoming an argument when two files with IIFEs are concatenated) ;(() => { const name = 'Skywalker'; return name; })();
-
21.1 ๋ฌธ์ฅ์ ์์ ๋ถ๋ถ์์ ํ(Type)์ ๊ฐ์ ํฉ๋๋ค.
-
21.2 String:
// => this.reviewScore = 9; // bad const totalScore = this.reviewScore + ''; // good const totalScore = String(this.reviewScore);
-
21.3 Number:
Numberํ์ผ๋ก ๋ณํํ๋ ค๋ฉดparseInt๋ฅผ ์ฌ์ฉํ์ธ์. ํญ์ ํ๋ณํ์ ์ํ ๊ธฐ์(radix)๋ฅผ ์ธ์๋ก ์ ๋ฌํฉ๋๋ค.eslint rules:
radix.const inputValue = '4'; // bad const val = new Number(inputValue); // bad const val = +inputValue; // bad const val = inputValue >> 0; // bad const val = parseInt(inputValue); // good const val = Number(inputValue); // good const val = parseInt(inputValue, 10);
-
21.4 ์ด๋ค ์ด์ ๋ก
parseInt๊ฐ ๋ณ๋ชฉ์ด๋๊ณ , ์ฑ๋ฅ์ ์ธ ์ด์ ์์ Bitshift๋ฅผ ์ฌ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ, ๋ฌด์์(what) ์(why)์ ๋ํ ์ค๋ช ์ ๋๊ธ๋ก ๋จ๊ฒจ ์ฃผ์ธ์.// good /** * parseInt๊ฐ ๋ณ๋ชฉ์ด๋๊ณ ์์๊ธฐ ๋๋ฌธ์, * Bitshift ๋ฌธ์์ด์ ์์น๋ก ๊ฐ์ ๋ก ๋ณํํ์ฌ * ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค. */ const val = inputValue >> 0;
-
21.5 ์ฃผ์: Bitshift๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ์์น๋ 64-๋นํธ ๊ฐ๋ค๋ก ํํ๋์ด ์์ง๋ง, Bitshift๋ฅผ ์ฐ์ฐํ๋ฉด ํญ์ 32-๋นํธ ๋จ ์ ๋ฐ๋๋ก ๋๋ ค ์ฃผ์ด์ง๋๋ค(source). 32-๋นํธ ์ด์์ ๊ฐ์ ๋นํธ ์ด๋ํ๋ฉด ์์์น ๋ชปํ ํ๋์ ์ผ์ผํฌ ๊ฐ๋ฅ์ฑ์ด ์์ต๋๋ค. Discussion. ๋ถํธ์๋ 32-๋นํธ ์ ์์ ์ต๋ ๊ฐ์ 2,147,483,647์ ๋๋ค:
2147483647 >> 0 //=> 2147483647 2147483648 >> 0 //=> -2147483648 2147483649 >> 0 //=> -2147483647
-
21.6 Booleans:
const age = 0; // bad const hasAge = new Boolean(age); // good const hasAge = Boolean(age); // good const hasAge = !!age;
-
22.1 ํ๋์ ๋ฌธ์๋ก ๊ตฌ์ฑ๋ ์ด๋ฆ์ ํผํ์ธ์. ์ด๋ฆ์์ ์๋๋ฅผ ์ฝ์ ์ ์๋๋ก ํด์ผ ํฉ๋๋ค.
// bad function q() { // ...stuff... } // good function query() { // ..stuff.. }
-
22.2 ๊ฐ์ฒด, ํจ์ ์ธ์คํด์ค์๋ camelCase(์๋ฌธ์๋ก ์์)๋ฅผ ์ฌ์ฉํ์ธ์.
eslint rules:
camelcase.// bad const OBJEcttsssss = {}; const this_is_my_object = {}; function c() {} // good const thisIsMyObject = {}; function thisIsMyFunction() {}
-
22.3 ํด๋์ค์ ์์ฑ์๋ PascalCase(๋๋ฌธ์๋ก ์์)๋ฅผ ์ฌ์ฉํ์ธ์.
// bad function user(options) { this.name = options.name; } const bad = new user({ name: 'nope', }); // good class User { constructor(options) { this.name = options.name; } } const good = new User({ name: 'yup', });
-
22.4 Private ์์ฑ ์ด๋ฆ์ ์์ ๋ฐ์ค
_์ ์ฌ์ฉํ์ธ์.eslint rules:
no-underscore-dangle.// bad this.__firstName__ = 'Panda'; this.firstName_ = 'Panda'; // good this._firstName = 'Panda';
-
22.5
this์ ๋ํ ์ฐธ์กฐ๋ฅผ ์ ์ฅํ์ง ์์ต๋๋ค. ์ ๋ก์ฐ ํจ์ ๋๋ Function#bind๋ฅผ ์ฌ์ฉํ์ธ์.// bad function foo() { const self = this; return function () { console.log(self); }; } // bad function foo() { const that = this; return function () { console.log(that); }; } // good function foo() { return () => { console.log(this); }; }
-
22.6 ํ์ผ์ ํ๋์ ํด๋์ค๋ก ์ถ์ถ(Export)ํ ๊ฒฝ์ฐ ํ์ผ ์ด๋ฆ์ ํด๋์ค ์ด๋ฆ๊ณผ ์ ํํ๊ฒ ์ผ์นํด์ผ ํฉ๋๋ค.
// file contents class CheckBox { // ... } export default CheckBox; // in some other file // bad import CheckBox from './checkBox'; // bad import CheckBox from './check_box'; // good import CheckBox from './CheckBox';
-
22.7 export-default ํจ์์ ๊ฒฝ์ฐ, camelCase(์๋ฌธ์๋ก ์์)๋ฅผ ์ฌ์ฉํ์ธ์. ํ์ผ์ด๋ฆ์ ํจ์์ด๋ฆ๊ณผ ๋์ผํด์ผ ํฉ๋๋ค.
function makeStyleGuide() { } export default makeStyleGuide;
-
22.8 ์ฑ๊ธํค(singleton) / ํจ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(function library) / ๋จ์ํ ๊ฐ์ฒด(bare object)๋ฅผ ์ถ์ถํ๋ ๊ฒฝ์ฐ, PascalCase(๋๋ฌธ์๋ก ์์)๋ฅผ ์ฌ์ฉํ์ธ์.
const AirbnbStyleGuide = { es6: { } }; export default AirbnbStyleGuide;
-
23.1 ์์ฑ์ ๋ํ ์ ๊ทผ์(Accessor) ํจ์๋ ํ์ํ์ง ์์ต๋๋ค.
-
23.2 ์ ๊ทผ์ ํจ์๊ฐ ํ์ํ ๊ฒฝ์ฐ
getVal()๊ณผsetVal('hello')๋ก ํ์ธ์.// bad dragon.age(); // good dragon.getAge(); // bad dragon.age(25); // good dragon.setAge(25);
-
23.3 ์์ฑ์ด
boolean์ ๊ฒฝ์ฐisVal()๋๋hasVal()๋ก ํ์ธ์.// bad if (!dragon.age()) { return false; } // good if (!dragon.hasAge()) { return false; }
-
23.4 ์ผ๊ด๋๋ค๋ฉด,
get()๊ณผset()ํจ์๋ฅผ ์์ฑํด๋ ์ข์ต๋๋ค.class Jedi { constructor(options = {}) { const lightsaber = options.lightsaber || 'blue'; this.set('lightsaber', lightsaber); } set(key, val) { this[key] = val; } get(key) { return this[key]; } }
-
24.1 (DOM ์ด๋ฒคํธ, Backbone ์ด๋ฒคํธ)์ฒ๋ผ ์์ ์ ์ด๋ฒคํธ ํ์ด๋ก๋ ๊ฐ์ ์ ๋ฌํ๋ ค๋ฉด ์์๊ฐ ๋์ ํด์์ธ์๋ฅผ ์ ๋ฌํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๋์ค์ ๊ฐ๋ฐ์๊ฐ ์ด๋ฒคํธ์ ๊ด๋ จ๋ ๋ชจ๋ ํธ๋ค๋ฌ๋ฅผ ์ฐพ์ ์ ๋ฐ์ดํธํ์ง ์๊ณ ์ด๋ฒคํธ ํ์ด๋ก๋์ ๊ฐ์ ์ถ๊ฐํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค๋ฉด:
// bad $(this).trigger('listingUpdated', listing.id); ... $(this).on('listingUpdated', function (e, listingId) { // do something with listingId });
๋ณด๋ค ์๋์ชฝ์ด ๋ ์ ํธ๋จ:
// good $(this).trigger('listingUpdated', { listingId: listing.id }); ... $(this).on('listingUpdated', function (e, data) { // do something with data.listingId });
-
25.1 jQuery ๊ฐ์ฒด ๋ณ์ ์์๋
$๋ก ๊ตฌ๋ถํฉ๋๋ค.// bad const sidebar = $('.sidebar'); // good const $sidebar = $('.sidebar'); // good const $sidebarBtn = $('.sidebar-btn');
-
25.2 jQuery์ ๊ฒ์ ๊ฒฐ๊ณผ๋ฅผ ์บ์ํฉ๋๋ค.
// bad function setSidebar() { $('.sidebar').hide(); // ...stuff... $('.sidebar').css({ 'background-color': 'pink' }); } // good function setSidebar() { const $sidebar = $('.sidebar'); $sidebar.hide(); // ...stuff... $sidebar.css({ 'background-color': 'pink' }); }
-
25.3 DOM์ ๊ฒ์์๋
$('.sidebar ul')๋๋$('.sidebar > ul')๊ณผ ๊ฐ์ Cascading์ ์ฌ์ฉํ์ธ์. jsPerf -
25.4 jQuery ๊ฐ์ฒด์ ๊ฒ์์๋ ๋ฒ์๊ฐ์๋
find๋ฅผ ์ฌ์ฉํ์ธ์.// bad $('ul', '.sidebar').hide(); // bad $('.sidebar').find('ul').hide(); // good $('.sidebar ul').hide(); // good $('.sidebar > ul').hide(); // good $sidebar.find('ul').hide();
- 26.1 Kangax์ ES5 ํธํ์ฑ ํ๋ฅผ ์ฐธ์กฐํ์ธ์.
- 27.1 ์ด๊ฒ์ ES6 ๋ช ์ธ ๋งํฌ๋ฅผ ๋ชจ์ ๋์ ๊ฒ์ ๋๋ค.
- ์ ๋ก์ฐ ํจ์(Arrow Functions)
- ํด๋์ค(Classes)
- ๊ฐ์ฒด ๋จ์ถ ๊ตฌ๋ฌธ(Object Shorthand)
- ์์ฑ ๋จ์ถ ๊ตฌ๋ฌธ(Object Concise)
- ๊ณ์ฐ๋ ์์ฑ ์ด๋ฆ(Object Computed Properties)
- ํ ํ๋ฆฟ ๋ฌธ์์ด(Template Strings)
- ๊ตฌ์กฐํ ๋์ (Destructuring)
- ๊ธฐ๋ณธ ๋งค๊ฐ๋ณ์(Default Parameters)
- ๋ ์คํธ(Rest)
- ๋ฐฐ์ด ์คํ๋ ๋(Array Spreads)
- Let๊ณผ Const(Let and Const)
- ์ดํฐ๋ ์ดํฐ์ ์ ๋๋ ์ดํฐ(Iterators and Generators)
- ๋ชจ๋(Modules)
-
28.1 ๋ฌผ๋ก ํด์ผ ํฉ๋๋ค.
function () { return true; }
-
28.2 ๋ฌผ๋ก ์ฌ๊ฐํ๊ฒ:
-
๋๋ถ๋ถ ํ ์คํธ ํ๋ ์์ํฌ๋ฅผ ์ด์ฉํ์ฌ ํ ์คํธ๋ฅผ ์์ฑํฉ๋๋ค.
-
์์ ๊ธฐ๋ฅ์ ํจ์๋ฅผ ์์ฃผ ์ฐ๊ณ ์ด๋ณ์ด ๋ฐ์ํ ์ ์๋ ๋ถ๋ถ์ ์ต์ํํ๊ธฐ ์ํด ๋ ธ๋ ฅํฉ๋๋ค.
-
stubs์ mocks์ ์ฃผ์ํ์ธ์. ์ด ๊ฒ๋ค๋ก ์ธํด ํ ์คํธ๊ฐ ๊นจ์ง๊ธฐ ์ฝ์ต๋๋ค.
-
Airbnb๋
mocha๋ฅผ ์ด์ฉํ๊ณ ์์ต๋๋ค. ์๊ฒ ๋ถํ ๋ ๊ฐ๋ณ ๋ชจ๋์tape์ ์ฌ์ฉํฉ๋๋ค. -
์ง๊ธ์ ๋ฌ์ฑํ ํ์๊ฐ ์์ด๋ 100%์ ํ ์คํธ ์ปค๋ฒ๋ฆฌ์ง๋ฅผ ๋ชฉํ๋กํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
-
๋ฒ๊ทธ๋ฅผ ์์ ํ ๋ ๋ง๋ค ํ๊ท ํ ์คํธ๋ฅผ ์๋๋ค. ํ๊ท ํ ์คํธ ์๋ ๋ฒ๊ทธ ์์ ์ ๋์ค์ ๋ฐ๋์ ๋ค์ ์ถํํ ๊ฒ์ ๋๋ค.
- On Layout & Web Performance
- String vs Array Concat
- Try/Catch Cost In a Loop
- Bang Function
- jQuery Find vs Context, Selector
- innerHTML vs textContent for script text
- Long String Concatenation
- Loading...
Learning ES6
- Draft ECMA 2015 (ES6) Spec
- ExploringJS
- ES6 Compatibility Table
- Comprehensive Overview of ES6 Features
Read This
Tools
- Code Style Linters
Other Style Guides
- Google JavaScript Style Guide
- jQuery Core Style Guidelines
- Principles of Writing Consistent, Idiomatic JavaScript
Other Styles
- Naming this in nested functions - Christian Johansen
- Conditional Callbacks - Ross Allen
- Popular JavaScript Coding Conventions on Github - JeongHoon Byun
- Multiple var statements in JavaScript, not superfluous - Ben Alman
Further Reading
- Understanding JavaScript Closures - Angus Croll
- Basic JavaScript for the impatient programmer - Dr. Axel Rauschmayer
- You Might Not Need jQuery - Zack Bloom & Adam Schwartz
- ES6 Features - Luke Hoban
- Frontend Guidelines - Benjamin De Cock
Books
- JavaScript: The Good Parts - Douglas Crockford
- JavaScript Patterns - Stoyan Stefanov
- Pro JavaScript Design Patterns - Ross Harmes and Dustin Diaz
- High Performance Web Sites: Essential Knowledge for Front-End Engineers - Steve Souders
- Maintainable JavaScript - Nicholas C. Zakas
- JavaScript Web Applications - Alex MacCaw
- Pro JavaScript Techniques - John Resig
- Smashing Node.js: JavaScript Everywhere - Guillermo Rauch
- Secrets of the JavaScript Ninja - John Resig and Bear Bibeault
- Human JavaScript - Henrik Joreteg
- Superhero.js - Kim Joar Bekkelund, Mads Mobรฆk, & Olav Bjorkoy
- JSBooks - Julien Bouquillon
- Third Party JavaScript - Ben Vinegar and Anton Kovalyov
- Effective JavaScript: 68 Specific Ways to Harness the Power of JavaScript - David Herman
- Eloquent JavaScript - Marijn Haverbeke
- You Don't Know JS: ES6 & Beyond - Kyle Simpson
Blogs
- DailyJS
- JavaScript Weekly
- JavaScript, JavaScript...
- Bocoup Weblog
- Adequately Good
- NCZOnline
- Perfection Kills
- Ben Alman
- Dmitry Baranovskiy
- Dustin Diaz
- nettuts
Podcasts
์ด ๊ฒ์ ๋ณธ ์คํ์ผ ๊ฐ์ด๋๋ฅผ ์ฌ์ฉํ๋ ์กฐ์ง์ ๋ชฉ๋ก์ ๋๋ค. ์ด ๋ชฉ๋ก์ ์ถ๊ฐํ๊ณ ์ถ๋ค๋ฉด, pull request๋ฅผ ํ๊ฑฐ๋ issue๋ฅผ ํตํด ์๋ ค์ฃผ์ธ์.
- Aan Zee: AanZee/javascript
- Adult Swim: adult-swim/javascript
- Airbnb: airbnb/javascript
- Apartmint: apartmint/javascript
- Avalara: avalara/javascript
- Billabong: billabong/javascript
- Bisk: bisk/javascript
- Blendle: blendle/javascript
- ComparaOnline: comparaonline/javascript
- Compass Learning: compasslearning/javascript-style-guide
- DailyMotion: dailymotion/javascript
- Digitpaint digitpaint/javascript
- Ecosia: ecosia/javascript
- Evernote: evernote/javascript-style-guide
- Evolution Gaming: evolution-gaming/javascript
- ExactTarget: ExactTarget/javascript
- Expensify Expensify/Style-Guide
- Flexberry: Flexberry/javascript-style-guide
- Gawker Media: gawkermedia/javascript
- General Electric: GeneralElectric/javascript
- GoodData: gooddata/gdc-js-style
- Grooveshark: grooveshark/javascript
- How About We: howaboutwe/javascript
- Huballin: huballin/javascript
- HubSpot: HubSpot/javascript
- Hyper: hyperoslo/javascript-playbook
- InfoJobs: InfoJobs/JavaScript-Style-Guide
- Intent Media: intentmedia/javascript
- Jam3: Jam3/Javascript-Code-Conventions
- JeopardyBot: kesne/jeopardy-bot
- JSSolutions: JSSolutions/javascript
- Kinetica Solutions: kinetica/javascript
- Mighty Spring: mightyspring/javascript
- MinnPost: MinnPost/javascript
- MitocGroup: MitocGroup/javascript
- ModCloth: modcloth/javascript
- Money Advice Service: moneyadviceservice/javascript
- Muber: muber/javascript
- National Geographic: natgeo/javascript
- National Park Service: nationalparkservice/javascript
- Nimbl3: nimbl3/javascript
- Orion Health: orionhealth/javascript
- OutBoxSoft: OutBoxSoft/javascript
- Peerby: Peerby/javascript
- Razorfish: razorfish/javascript-style-guide
- reddit: reddit/styleguide/javascript
- React: /facebook/react/blob/master/CONTRIBUTING.md#style-guide
- REI: reidev/js-style-guide
- Ripple: ripple/javascript-style-guide
- SeekingAlpha: seekingalpha/javascript-style-guide
- Shutterfly: shutterfly/javascript
- Springload: springload/javascript
- StudentSphere: studentsphere/javascript
- Target: target/javascript
- TheLadders: TheLadders/javascript
- T4R Technology: T4R-Technology/javascript
- VoxFeed: VoxFeed/javascript-style-guide
- Weggo: Weggo/javascript
- Zillow: zillow/javascript
- ZocDoc: ZocDoc/javascript
์ด ์คํ์ผ ๊ฐ์ด๋๋ ๋ค๋ฅธ ์ธ์ด๋ก๋ ์ด์ฉํ ์ ์์ต๋๋ค.
Brazilian Portuguese: armoucar/javascript-style-guide
Bulgarian: borislavvv/javascript
Catalan: fpmweb/javascript-style-guide
Chinese (Simplified): sivan/javascript-style-guide
Chinese (Traditional): jigsawye/javascript
French: nmussy/javascript-style-guide
German: timofurrer/javascript-style-guide
Italian: sinkswim/javascript-style-guide
Japanese: mitsuruog/javacript-style-guide
Korean: tipjs/javascript-style-guide
Polish: mjurczyk/javascript
Russian: uprock/javascript
Spanish: paolocarrasco/javascript-style-guide
Thai: lvarayut/javascript-style-guide
- Find us on gitter.
(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.
We encourage you to fork this guide and change the rules to fit your team's style guide. Below, you may list some amendments to the style guide. This allows you to periodically update your style guide without having to deal with merge conflicts.