Skip to content
Kang Log
Go back

코드컨벤션

Updated:

코드컨벤션

#자바스크립트 #중요 #개념

참조


[!black]- 예시


// bad

var a = 1;

var b = 2;



// good

const a = 1;

const b = 2;

[!black]- 예시


// bad

var count = 1;

if (true) {

count += 1;

}



// good, use the let.

let count = 1;

if (true) {

count += 1;

}

객체


[!black]- 예시

// bad
const item = new Object();
/ good
const item = {};

[!black]- 예시


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,

};

[!black]- 예시


// bad

const atom = {

value: 1,



addValue: function (value) {

return atom.value + value;

},

};



// good

const atom = {

value: 1,



addValue(value) {

return atom.value + value;

},

};

[!black]- 예시


const lukeSkywalker = 'Luke Skywalker';



// bad

const obj = {

lukeSkywalker: lukeSkywalker,

};



// good

const obj = {

lukeSkywalker,

};

[!black]- 예시


// bad

const bad = {

foo: 3,

bar: 4,

'data-blah': 5,

};



// good

const good = {

foo: 3,

bar: 4,

'data-blah': 5,

};

const object = {

a: 1,

hasOwnProperty: false,

};



// 이 경우에는 오류가 발생합니다.

console.log(object.hasOwnProperty('a')); // TypeError: object.hasOwnProperty is not a function

// bad

console.log(object.hasOwnProperty(key));



// good

console.log(Object.prototype.hasOwnProperty.call(object, key));



// best

const has = Object.prototype.hasOwnProperty; // 모듈스코프에서 한 번 캐시하세요.

console.log(has.call(object, key));

/* or \*/

import has from 'has'; // https://www.npmjs.com/package/has

console.log(has(object, key));

[!black]- 예시


// very bad

const original = { a: 1, b: 2 };

const copy = Object.assign(original, { c: 3 }); // `original`을 변조합니다 ಠ_ಠ

delete copy.a; // 그래서 이렇게 합니다



// bad

const original = { a: 1, b: 2 };

const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 }



// good

const original = { a: 1, b: 2 };

const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 }



const { a, ...noA } = copy; // noA => { b: 2, c: 3 }

배열


[!black]- 예시


// bad

const items = new Array();



// good

const items = [];

[!black]- 예시


const someStack = [];



// bad

someStack[someStack.length] = 'abracadabra';



// good

someStack.push('abracadabra');

[!black]- 예시


const foo = document.querySelectorAll('.foo');



// good

const nodes = Array.from(foo);



// best

const nodes = [...foo];

[!black]- 예시


const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 };



// bad

const arr = Array.prototype.slice.call(arrLike);



// good

const arr = Array.from(arrLike);

[!black]- 예시


// bad

const baz = [...foo].map(bar);



// good

const baz = Array.from(foo, bar);

white

Array.from은 map에 비해 메모리는 적게쓰지만, 오래걸린다는 단점이 있음 StackOverFlow

[!black]- 예시


// good

[1, 2, 3].map((x) => {

const y = x + 1;

return x * y;

});



// good

[1, 2, 3].map((x) => x + 1);



// bad - no returned value means `acc` becomes undefined after the first iteration

[

[0, 1],

[2, 3],

[4, 5],

].reduce((acc, item, index) => {

const flatten = acc.concat(item);

acc[index] = flatten;

});



// good

[

[0, 1],

[2, 3],

[4, 5],

].reduce((acc, item, index) => {

const flatten = acc.concat(item);

acc[index] = flatten;

return flatten;

});



// bad

inbox.filter((msg) => {

const { subject, author } = msg;

if (subject === 'Mockingbird') {

return author === 'Harper Lee';

} else {

return false;

}

});



// good

inbox.filter((msg) => {

const { subject, author } = msg;

if (subject === 'Mockingbird') {

return author === 'Harper Lee';

}



return false;

});

reduce사용할 때, 초기값 설정 안하면 배열의 0번 인덱스를 초기값으록 가진다

[!black]- 예시


// bad

const arr = [

[0, 1],

[2, 3],

[4, 5],

];



const objectInArray = [

{

id: 1,

},

{

id: 2,

},

];



const numberInArray = [1, 2];



// good

const arr = [

[0, 1],

[2, 3],

[4, 5],

];



const objectInArray = [

{

id: 1,

},

{

id: 2,

},

];



const numberInArray = [1, 2];

비구조화


[!black]- 예시


// 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}`;

}

[!black]- 예시


// 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, top } = processInput(input);

문자열


[!black]- 에시


// 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.';

[!black]- 예시


// 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}?`;

}

함수


[!black]- 예시


// bad

function foo() {

// ...

}



// bad

const foo = function () {

// ...

};



// good

// 변수 참조 호출과 구분되는 이름

const short = function longUniqueMoreDescriptiveLexicalFoo() {

// ...

};

[!black]- 예시


// 즉시 호출 함수 표현식 (IIFE)

(function () {

console.log('Welcome to the Internet. Please follow me.');

})();

white

즉시 함수 표현식에 방법은 여러 방법이 있지만 전체를 괄호로 묶는 방식을 사용하자 (function() {})() [X] (function() {}()) [O]

[!black]- 예시


// bad

if (currentUser) {

function test() {

console.log('Nope.');

}

}



// good

let test;

if (currentUser) {

test = () => {

console.log('Yup.');

};

}

white

표현식: 표현식은 값을 계산하고 반환합니다. 구문: 구문은 특정 작업을 수행하며, 프로그램의 흐름을 제어합니다. 구문과 표현식

[!black]- 예시


// bad

function concatenateAll() {

const args = Array.prototype.slice.call(arguments);

return args.join('');

}



// good

function concatenateAll(...args) {

return args.join('');

}

[!black]- 에시


// really bad

function handleThings(opts) {

// 안돼요! 우리는 함수 인자를 변경하면 안됩니다.

// 더 안 좋은 경우: 만약 opts가 falsy한 값일 경우 당신이 원하는 객체로

// 설정되겠지만, 이는 미묘한 버그를 일으킬 수 있습니다.

opts = opts || {};

// ...

}



// still bad

function handleThings(opts) {

if (opts === void 0) {

opts = {};

}

// ...

}



// good

function handleThings(opts = {}) {

// ...

}

white

void 0 은 undefined 를 뜻한다, void 0 == null: true, void 0 === null: false, void 0 == false: false

[!black]- 에시


var b = 1;

// bad

function count(a = b++) {

console.log(a);

}

count(); // 1

count(); // 2

count(3); // 3

count(); // 3

white

사이드이펙트(부수효과): 하나의 동작에, 두개 이상의 효과를 가져다 주는 것이라고 이해했다 함수를 실행 → 전체 상태가 변화 (리액트) 함수를 실행 → 외부 변수의 값이 변화 값을 할당 → 다른 값도 변화

사이드 이펙트가 나쁜건 아니지만, 유지보수의 측면에서 순수함수 를 작성하는게 좋다고 한다 순수함수: 오직 함수의 입력만이 함수의 결과에 영향을 주는 함수

[!black]- 에시


// bad

function handleThings(opts = {}, name) {

// ...

}



// good

function handleThings(name, opts = {}) {

// ...

}

[!black]- 예시


// bad

const f = function () {};

const g = function () {};

const h = function () {};



// good

const x = function () {};

const y = function a() {};

[!black]- 예시


// bad

function f1(obj) {

obj.key = 1;

}



// good

function f2(obj) {

const key = Object.prototype.hasOwnProperty.call(obj, 'key')

? obj.key

: 1;

}

재귀함수에서 배열에 값을 담는 상황이면 어떡해야하지..?

[!black]- 예시


// 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) {

// ...

}

[!black]- 예시


// bad

function foo(bar, baz, quux) {

// ...

}



// good

function foo(bar, baz, quux) {

// ...

}



// bad

console.log(foo, bar, baz);



// good

console.log(foo, bar, baz);

화살표 함수


[!black]- 예시


// 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;

});

[!black]- 예시


// bad

[1, 2, 3].map((number) => {

const nextNumber = number + 1;

`A string containing the ${nextNumber}.`;

});



// good

[1, 2, 3].map((number) => `A string containing the ${number}.`);



// good

[1, 2, 3].map((number) => {

const nextNumber = number + 1;

return `A string containing the ${nextNumber}.`;

});



// good

[1, 2, 3].map((number, index) => ({

[index]: number,

}));



// 암시적 반환없이 사이드 이펙트를 수반합니다

function foo(callback) {

const val = callback();

if (val === true) {

// callback이 참을 반환하면 뭔가를 수행합니다

}

}



let bool = false;



// bad bool 이라는 외부변수가 바뀌는 사이드이펙트가 있으니 중괄호로 감싸야함

foo(() => (bool = true));



// good

foo(() => {

bool = true;

});

[!black]- 예시


// bad

['get', 'post', 'put'].map((httpMethod) =>

Object.prototype.hasOwnProperty.call(

httpMagicObjectWithAVeryLongName,

httpMethod

)

);



// good

['get', 'post', 'put'].map((httpMethod) =>

Object.prototype.hasOwnProperty.call(

httpMagicObjectWithAVeryLongName,

httpMethod

)

);

[!black]- 예시


// bad

const itemHeight = (item) =>

item.height > 256 ? item.largeSize : item.smallSize;



// bad

const itemHeight = (item) =>

item.height > 256 ? item.largeSize : item.smallSize;



// good

const itemHeight = (item) =>

item.height > 256 ? item.largeSize : item.smallSize;



// good

const itemHeight = (item) => {

const { height, largeSize, smallSize } = item;

return height > 256 ? largeSize : smallSize;

};

[!black]- 예시


// bad

(foo) => bar;



(foo) => bar;



// good

(foo) => bar;

(foo) => bar;

(foo) => bar;

클래스 & 생성자


[!black]- 예시


// 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;

}

}

[!black]- 예시


// 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);

[!black]- 예시


class Jedi {

constructor(options = {}) {

this.name = options.name || 'no name';

}



getName() {

return this.name;

}



toString() {

return `Jedi - ${this.getName()}`;

}

}

[!black]- 예시


// bad

class Jedi {

constructor() {}



getName() {

return this.name;

}

}



// bad

class Rey extends Jedi {

constructor(...args) {

super(...args);

}

}



// good

class Rey extends Jedi {

constructor(...args) {

super(...args);

this.name = 'Rey';

}

}

[!black]- 예시


// bad

class Foo {

bar() {

return 1;

}

bar() {

return 2;

}

}



// good

class Foo {

bar() {

return 1;

}

}



// good

class Foo {

bar() {

return 2;

}

}

[!black]- 예시


// bad

class Foo {

bar() {

console.log('bar');

}

}



// good - this를 사용했습니다

class Foo {

bar() {

console.log(this.bar);

}

}



// good - constructor가 면제됩니다

class Foo {

constructor() {

// ...

}

}



// good - 정적 메소드는 this를 사용하지 않는다고 예상할 수 있습니다

class Foo {

static bar() {

console.log('bar');

}

}

모듈


[!black]- 예시


// 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;

[!black]- 예시


// bad

// filename es6.js

export { es6 as default } from './AirbnbStyleGuide';



// good

// filename es6.js

import { es6 } from './AirbnbStyleGuide';

export default es6;

[!black]- 예시 // bad import foo from ‘foo’; // … 또 다른 imports … // import { named1, named2 } from ‘foo’;

// good import foo, { named1, named2 } from ‘foo’;

// good import foo, { named1, named2, } from ‘foo’;

[!black]- 예시


// bad

let foo = 3;

export { foo };



// good

const foo = 3;

export { foo };

[!black]- 예시


// bad

import fooSass from 'css!sass!foo.scss';

import barCss from 'style!css!bar.css';



// good

import fooSass from 'foo.scss';

import barCss from 'bar.css';

[!black]- 예시


// bad

import foo from './foo.js';

import bar from './bar.jsx';

import baz from './baz/index.jsx';



// good

import foo from './foo';

import bar from './bar';

import baz from './baz';

이터레이터 & 제네레이터


[!black]- 예시


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;



// bad

const increasedByOne = [];

for (let i = 0; i < numbers.length; i++) {

increasedByOne.push(numbers[i] + 1);

}



// good

const increasedByOne = [];

numbers.forEach((num) => {

increasedByOne.push(num + 1);

});



// best (keeping it functional)

const increasedByOne = numbers.map((num) => num + 1);

white

배열을 이터레이트할 때  map() every()  filter()  find()  findIndex()  reduce()  some() 을 사용 배열을 생성할 때는 Object.keys() / Object.values() / Object.entries()를 사용 개인적으로 가장 충격적이었던 사실..

속성


[!black]- 예시


const luke = {

jedi: true,

age: 28,

};



// bad

const isJedi = luke['jedi'];



// good

const isJedi = luke.jedi;

[!black]- 예시


const luke = {

jedi: true,

age: 28,

};



function getProp(prop) {

return luke[prop];

}



const isJedi = getProp('jedi');

[!black]- 예시


// bad

const binary = Math.pow(2, 10);



// good

const binary = 2 ** 10;

이미 한번 당함 (Math.pow는 실수연산이라 큰 숫자에서 오차가 생김)

변수


[!black]- 예시


// bad

const items = getItems(),

goSportsTeam = true,

dragonball = 'z';



// bad

// (위 코드와 비교해 실수를 짚어보세요)

const items = getItems(),

goSportsTeam = true;

dragonball = 'z';



// good

const items = getItems();

const goSportsTeam = true;

const dragonball = 'z';

[!black]- 예시


// 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;

[!black]- 예시


// bad - unnecessary function call

function checkName(hasName) {

const name = getName();



if (hasName === 'test') {

return false;

}



if (name === 'test') {

this.setName('');

return false;

}



return name;

}



// good

function checkName(hasName) {

if (hasName === 'test') {

return false;

}



const name = getName();



if (name === 'test') {

this.setName('');

return false;

}



return name;

}

코드 윗쪽에서 사용할 변수를 전부 선언해야하는 강박에서 자유로워질수 있다

[!black]- 예시


// bad

(function example() {

// 자바스크립트는 이것을

// let a = ( b = ( c = 1 ) );

// 로 해석합니다.

// let 키워드는 변수 a에만 적용됩니다.

// 변수 b와 c는 전역 변수가 됩니다.

let a = (b = c = 1);

})();



console.log(a); // throws ReferenceError

console.log(b); // 1

console.log(c); // 1



// good

(function example() {

let a = 1;

let b = a;

let c = a;

})();



console.log(a); // throws ReferenceError

console.log(b); // throws ReferenceError

console.log(c); // throws ReferenceError



// `const`에도 동일하게 적용됩니다

이것도 좀 충격적이네

[!black]- 예시


// bad

const foo = superLongLongLongLongLongLongLongLongFunctionName();



// bad

const foo = 'superLongLongLongLongLongLongLongLongString';



// good

const foo = superLongLongLongLongLongLongLongLongFunctionName();



// good

const foo = 'superLongLongLongLongLongLongLongLongString';

호이스팅


[!black]- 예시


// (전역 변수 notDefined가 존재하지 않는다고 판정한 경우)

// 동작하지 않습니다

function example() {

console.log(notDefined); // => throws a ReferenceError

}



// 그 변수를 참조하는 코드의 뒤에서 그 변수를 선언한 경우

// 변수가 호이스트된 상태에서 동작합니다.

// 주의:`true` 라는 값 자체는 호이스트되지 않습니다.

function example() {

console.log(declaredButNotAssigned); // => undefined

var declaredButNotAssigned = true;

}



// 인터프리터는 변수선언을 스코프의 선두에 호이스트합니다

// 위의 예는 다음과 같이 다시 쓸수 있습니다:

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;

}

[!black]- 예시


function example() {

console.log(anonymous); // => undefined



anonymous(); // => TypeError anonymous is not a function



var anonymous = function () {

console.log('anonymous function expression');

};

}

[!black]- 예시


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');

};

}

비교 연산자


[!black]- 예시


if ([0] && []) {

// true

// 배열(빈 배열 포함)은 객체이며, 객체는 참으로 평가됩니다.

}

[!black]- 예시


// bad

if (isValid === true) {

// ...

}



// good

if (isValid) {

// ...

}



// bad

if (name) {

// ...

}



// good

if (name !== '') {

// ...

}



// bad

if (collection.length) {

// ...

}

*이것도 간과하기 쉬운 컨벤션인듯
 자세한 내용은*
 [Truth Equality and JavaScript](https://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/#more-2108)

[!black]- 예시


// bad

switch (foo) {

case 1:

let x = 1;

break;

case 2:

const y = 2;

break;

case 3:

function f() {

// ...

}

break;

default:

class C {}

}



// good

switch (foo) {

case 1: {

let x = 1;

break;

}

case 2: {

const y = 2;

break;

}

case 3: {

function f() {

// ...

}

break;

}

case 4:

bar();

break;

default: {

class C {}

}

}

[!black]- 예시


// bad

const foo = a ? a : b;

const bar = c ? true : false;

const baz = c ? false : true;



// good

const foo = a || b;

const bar = !!c;

const baz = !c;

[!black]- 예시


// bad

const foo = (a && b < 0) || c > 0 || d + 1 === 0;



// bad

const bar = a ** b - (5 % d);



// bad

// (a || b) && c 으로 혼동할 수 있습니다.

if (a || (b && c)) {

return d;

}



// good

const foo = (a && b < 0) || c > 0 || d + 1 === 0;



// good

const bar = a ** b - (5 % d);



// good

if (a || (b && c)) {

return d;

}



// good

const bar = a + (b / c) * d;

블록


[!black]- 예시


// bad

if (test) return false;



// good

if (test) return false;



// good

if (test) {

return false;

}



// bad

function foo() {

return false;

}



// good

function bar() {

return false;

}

[!black]- 예시


// bad

if (test) return false;



// good

if (test) return false;



// good

if (test) {

return false;

}



// bad

function foo() {

return false;

}



// good

function bar() {

return false;

}

[!black]- 예시


// bad

function foo() {

if (x) {

return x;

} else {

return y;

}

}



// bad

function cats() {

if (x) {

return x;

} else if (y) {

return y;

}

}



// bad

function dogs() {

if (x) {

return x;

} else {

if (y) {

return y;

}

}

}



// good

function foo() {

if (x) {

return x;

}



return y;

}



// good

function cats() {

if (x) {

return x;

}



if (y) {

return y;

}

}



// good

function dogs(x) {

if (x) {

if (z) {

return y;

}

} else {

return z;

}

}

제어문


[!black]- 예시


// bad

if (

(foo === 123 || bar === 'abc') &&

doesItLookGoodWhenItBecomesThatLong() &&

isThisReallyHappening()

) {

thing1();

}



// bad

if (foo === 123 && bar === 'abc') {

thing1();

}



// bad

if (foo === 123 && bar === 'abc') {

thing1();

}



// bad

if (foo === 123 && bar === 'abc') {

thing1();

}



// good

if (foo === 123 && bar === 'abc') {

thing1();

}



// good

if (

(foo === 123 || bar === 'abc') &&

doesItLookGoodWhenItBecomesThatLong() &&

isThisReallyHappening()

) {

thing1();

}



// good

if (foo === 123 && bar === 'abc') {

thing1();

}

[!black]- 예시


// bad

!isRunning && startRunning();



// good

if (!isRunning) {

startRunning();

}

주석


[!black]- 예시


// bad

// make()는 전달된 태그명을 기반으로

// 새로운 요소를 반환한다.

//

// @param {String} tag

// @return {Element} element

function make(tag) {

// ...



return element;

}



// good

/**

* make()는 전달된 태그명을 기반으로

* 새로운 요소를 반환한다.

*/

function make(tag) {

// ...



return element;

}

[!black]- 예시


// 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;

}

[!black]- 예시


// bad

//is current tab

const active = true;



// good

// is current tab

const active = true;



// bad

/**

*make()는 전달된 태그명을 기반으로

*새로운 요소를 반환한다.

*/

function make(tag) {

// ...



return element;

}



// good

/**

* make()는 전달된 태그명을 기반으로

* 새로운 요소를 반환한다.

*/

function make(tag) {

// ...



return element;

}

[!black]- 예시


class Calculator extends Abacus {

constructor() {

super();



// FIXME: 전역 변수를 사용해서는 안 됨

total = 0;

}

}

[!black]- 예시


class Calculator extends Abacus {

constructor() {

super();



// TODO: total은 옵션 파라메터로 설정해야함

this.total = 0;

}

}

공백


[!black]- 예시


// bad

function foo() {

∙∙∙∙let name;

}



// bad

function bar() {

let name;

}



// good

function baz() {

∙∙let name;

}

[!black]- 예시


// 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',

});

[!black]- 예시


// bad

if (isJedi) {

fight();

}



// good

if (isJedi) {

fight();

}



// bad

function fight() {

console.log('Swooosh!');

}



// good

function fight() {

console.log('Swooosh!');

}

[!black]- 예시


// bad

import { es6 } from './AirbnbStyleGuide';

// ...

export default es6;



// bad

import { es6 } from './AirbnbStyleGuide';

// ...

export default es6;↵





// good

import { es6 } from './AirbnbStyleGuide';

// ...

export default es6;↵

[!black]- 예시


// 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')

.classed('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);



// good

const leds = stage.selectAll('.led').data(data);

[!black]- 예시


// 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;

[!black]- 예시


// bad

function bar() {

console.log(foo);

}



// bad

if (baz) {

console.log(qux);

} else {

console.log(foo);

}



// bad

class Foo {

constructor(bar) {

this.bar = bar;

}

}



// good

function bar() {

console.log(foo);

}



// good

if (baz) {

console.log(qux);

} else {

console.log(foo);

}

[!black]- 예시


// bad

class Person {

constructor(fullName, email, birthday) {

this.fullName = fullName;



this.email = email;



this.setAge(birthday);

}



setAge(birthday) {

const today = new Date();



const age = this.getAge(today, birthday);



this.age = age;

}



getAge(today, birthday) {

// ..

}

}



// good

class Person {

constructor(fullName, email, birthday) {

this.fullName = fullName;

this.email = email;

this.setAge(birthday);

}



setAge(birthday) {

const today = new Date();

const age = getAge(today, birthday);

this.age = age;

}



getAge(today, birthday) {

// ..

}

}

[!black]- 예시


// bad

function bar(foo) {

return foo;

}



// good

function bar(foo) {

return foo;

}



// bad

if (foo) {

console.log(foo);

}



// good

if (foo) {

console.log(foo);

}



// bad

const foo = [1, 2, 3];

console.log(foo[0]);



// good

const foo = [1, 2, 3];

console.log(foo[0]);

[!black]- 예시


// bad

const foo = { clark: 'kent' };



// good

const foo = { clark: 'kent' };

[!black]- 예시


// bad

const foo =

jsonData &&

jsonData.foo &&

jsonData.foo.bar &&

jsonData.foo.bar.baz &&

jsonData.foo.bar.baz.quux &&

jsonData.foo.bar.baz.quux.xyzzy;



// 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 =

jsonData &&

jsonData.foo &&

jsonData.foo.bar &&

jsonData.foo.bar.baz &&

jsonData.foo.bar.baz.quux &&

jsonData.foo.bar.baz.quux.xyzzy;



// good

$.ajax({

method: 'POST',

url: 'https://airbnb.com/',

data: { name: 'John' },

})

.done(() => console.log('Congratulations!'))

.fail(() => console.log('You have failed this city.'));

[!black]- 예시


// bad

obj[foo];

obj['foo'];

var x = { [b]: a };

obj[foo[bar]];



// good

obj[foo];

obj['foo'];

var x = { [b]: a };

obj[foo[bar]];

white

eslint: computed-property-spacing

  • *"never" (default) disallows spaces inside computed property brackets*
  • *"always" requires one or more spaces inside computed property brackets*

이 말이 애매해서 찾아봤는데 그냥 “never”을 사용하라는 뜻인듯 싶다

[!black]- 예시


// bad

var obj = { foo: 42 };

var obj2 = { foo: 42 };



// good

var obj = { foo: 42 };

[!black]- 예시


// bad - 여러 개의 빈 줄

var x = 1;



var y = 2;



// bad - 파일 끝에 2개 이상의 빈 줄

var x = 1;

var y = 2;



// bad - 파일 시작에 1개 이상의 빈 줄



var x = 1;

var y = 2;



// good

var x = 1;

var y = 2;

쉼표


[!black]- 예시


// 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',

};

// bad - 마지막에 쉼표가 없는 경우 git diff

const hero = {

firstName: 'Florence',

- lastName: 'Nightingale'

+ lastName: 'Nightingale',

+ inventorOf: ['coxcomb chart', 'modern nursing']

};



// good - 마지막에 쉼표가 있는 경우 git diff

const hero = {

firstName: 'Florence',

lastName: 'Nightingale',

+ inventorOf: ['coxcomb chart', 'modern nursing'],

};

쉼표를 뒤에 붙이는 스타일을 유지해야만 git diffs에 불필요한 정보들이 들어가지 않는다

세미콜론


형변환 강제


[!black]- 예시


// => this.reviewScore = 9;



// bad

const totalScore = new String(this.reviewScore); // typeof totalScore is "object" not "string"



// bad

const totalScore = this.reviewScore + ''; // invokes this.reviewScore.valueOf()



// bad

const totalScore = this.reviewScore.toString(); // isn’t guaranteed to return a string



// good

const totalScore = String(this.reviewScore);

[!black]- 예시


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);

[!black]- 예시


// good

/**

* parseInt was the reason my code was slow.

* Bitshifting the String to coerce it to a

* Number made it a lot faster.

* 코드가 느린 원인은 parseInt였음.

* 비트 시프트를 통해 문자열을 강제 형변환하여

* 성능을 개선시킴.

*/

const val = inputValue >> 0;

[!black]- 예시


2147483647 >> 0; // => 2147483647

2147483648 >> 0; // => -2147483648

2147483649 >> 0; // => -2147483647

[!black]- 예시


const age = 0;



// bad

const hasAge = new Boolean(age);



// good

const hasAge = Boolean(age);



// best

const hasAge = !!age;

명명 규칙


[!black]- 예시


// bad

function q() {

// ...

}



// good

function query() {

// ...

}

[!black]- 예시


// bad

const OBJEcttsssss = {};

const this_is_my_object = {};

function c() {}



// good

const thisIsMyObject = {};

function thisIsMyFunction() {}

[!black]- 예시


// 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',

});

[!black]- 예시


// bad

this.__firstName__ = 'Panda';

this.firstName_ = 'Panda';

this._firstName = 'Panda';



// good

this.firstName = 'Panda';



// good, in environments where WeakMaps are available

// see https://kangax.github.io/compat-table/es6/#test-WeakMap

const firstNames = new WeakMap();

firstNames.set(this, 'Panda');

[!black]- 예시


// 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);

};

}

[!white] bind, apply, call 예시 공통점: 전부 첫번째 인자가 this의 값으로 들어감 차이점: bind는 말그대로 값들과 함수나 클래스를 묶어주는 느낌, apply, call은 즉시 호출 apply, call의 차이점: apply는 배열을 인자로 쓰고, call은 각각 변수를 인자롤 쓴다

function sum(a, b, c) {
return a + b + c;
}
const sum123 = sum.bind(null, 1, 2, 3);
const arr = [1, 2, 3];
console.log(sum123()); // 6
console.log(sum.apply(null,arr)); // 6
console.log(sum.call(null, 1, 2, 3)); // 6

[!black]- 예시


// 파일 1 내용

class CheckBox {

// ...

}

export default CheckBox;



// 파일 2 내용

export default function fortyTwo() { return 42; }



// 파일 3 내용

export default function insideDirectory() {}



// 다른 파일

// bad

import CheckBox from './checkBox'; // PascalCase import/export, camelCase filename

import FortyTwo from './FortyTwo'; // PascalCase import/filename, camelCase export

import InsideDirectory from './InsideDirectory'; // PascalCase import/filename, camelCase export



// bad

import CheckBox from './check_box'; // PascalCase import/export, snake_case filename

import forty_two from './forty_two'; // snake_case import/filename, camelCase export

import inside_directory from './inside_directory'; // snake_case import, camelCase export

import index from './inside_directory/index'; // requiring the index file explicitly

import insideDirectory from './insideDirectory/index'; // requiring the index file explicitly



// good

import CheckBox from './CheckBox'; // PascalCase export/import/filename

import fortyTwo from './fortyTwo'; // camelCase export/import/filename

import insideDirectory from './insideDirectory'; // camelCase export/import/directory name/implicit "index"

// ^ supports both insideDirectory.js and insideDirectory/index.js

[!black]- 예시


const AirbnbStyleGuide = {

es6: {},

};



export default AirbnbStyleGuide;

[!black]- 예시


// bad

import SmsContainer from './containers/SmsContainer';



// bad

const HttpRequests = [

// ...

];



// good

import SMSContainer from './containers/SMSContainer';



// good

const HTTPRequests = [

// ...

];



// also good

const httpRequests = [

// ...

];



// best

import TextMessageContainer from './containers/TextMessageContainer';



// best

const requests = [

// ...

];

[!black]- 예시


// bad

const PRIVATE_VARIABLE =

'should not be unnecessarily uppercased within a file';



// bad

export const THING_TO_BE_CHANGED = 'should obviously not be uppercased';



// bad

export let REASSIGNABLE_VARIABLE =

'do not use let with uppercase variables';



// ---



// allowed but does not supply semantic value

export const apiKey = 'SOMEKEY';



// better in most cases

export const API_KEY = 'SOMEKEY';



// ---



// bad - unnecessarily uppercases key while adding no semantic value

export const MAPPING = {

KEY: 'value',

};



// good

export const MAPPING = {

key: 'value',

};

접근자


[!black]- 예시


// bad

class Dragon {

get age() {

// ...

}



set age(value) {

// ...

}

}



// good

class Dragon {

getAge() {

// ...

}



setAge(value) {

// ...

}

}

[!black]- 예시


// bad

if (!dragon.age()) {

return false;

}



// good

if (!dragon.hasAge()) {

return false;

}

[!black]- 예시


class Jedi {

constructor(options = {}) {

const lightsaber = options.lightsaber || 'blue';

this.set('lightsaber', lightsaber);

}



set(key, val) {

this[key] = val;

}



get(key) {

return this[key];

}

}

이벤트


[!black]- 예시


// bad

$(this).trigger('listingUpdated', listing.id);



// ...



$(this).on('listingUpdated', (e, listingID) => {

// do something with listingID

});



// good

$(this).trigger('listingUpdated', { listingID: listing.id });



// ...



$(this).on('listingUpdated', (e, data) => {

// do something with data.listingID

});

제이쿼리


[!black]- 예시


// bad

const sidebar = $('.sidebar');



// good

const $sidebar = $('.sidebar');



// good

const $sidebarBtn = $('.sidebar-btn');

[!black]- 예시


// bad

function setSidebar() {

$('.sidebar').hide();



// ...



$('.sidebar').css({

'background-color': 'pink',

});

}



// good

function setSidebar() {

const $sidebar = $('.sidebar');

$sidebar.hide();



// ...



$sidebar.css({

'background-color': 'pink',

});

}

[!black]- 예시


// bad

$('ul', '.sidebar').hide();



// bad

$('.sidebar').find('ul').hide();



// good

$('.sidebar ul').hide();



// good

$('.sidebar > ul').hide();



// good

$sidebar.find('ul').hide();

Share this post on:

Previous Post
가상메모리
Next Post
동기화