Code convention: JavaScript
12 min readApr 6, 2021
Airbnb convention을 참고했습니다.
0. 기본 명명 규칙
- 객체, 함수, 인스턴스는 camelCase
- 클래스, 생성자는 PascalCase
- 참조를 this에 저장하지말고 화살표함수나 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);
};
}
- 파일 이름은 default export의 이름과 일치해야 합니다.
// 파일 1 내용
class CheckBox { //클래스니까 PascalCase
// ...
}
export default CheckBox; // 파일 2 내용
export default function fortyTwo() { return 42; } //함수니까 camelCase // 다른 파일에서 import // PascalCase export/import/filename
import CheckBox from './CheckBox'; // camelCase export/import/filenam
eimport fortyTwo from './fortyTwo';
- 두문자어와 이니셜은 모두 대문자이거나 모두 소문자입니다.
//bad
SmsContainer
HttpRequests //good
SMSContainer
HTTPRequests
httpRequests
1. 변수, 참조
- 변수를 선언할 때는 항상
const
나let
을 사용하세요. 이렇게 하지 않으면 전역 변수로 선언됩니다.
// bad
superPower = new SuperPower(); // good
const superPower = new SuperPower();
- 모든 참조에는 var대신 const를 사용하세요.
- 참조를 재할당 할 수 없게 함으로써, 이해하기 어려운 & 버그로 이어지는 코드를 방지합니다.
// bad
var a = 1;
var b = 2; // good
const a = 1;
const b = 2;
- 만약 참조를 재할당 해야 한다면
var
대신let
을 사용하세요
-var
처럼 함수스코프를 취하는 것보다는 블록스코프를 취하는 let이 더 낫습니다.
// bad
var count = 1;
if (true) {
count += 1;
} // good, use the let.
let count = 1;
if (true) {
count += 1;
}
let
과const
는 둘 다 블록스코프라는 것을 유의하세요.
- const와 let은 선언된 블록 안에서만 존재합니다.
{
let a = 1;
const b = 1;
}
console.log(a); // ReferenceError
console.log(b); // ReferenceError
2. 문자열
- 문자열에는 작은 따옴표
''
를 사용한다. - 100자가 넘는 문자열은 개행 없이 이어쓴다.(문자열 연결’+’ 을 이용해 여러 줄에 걸쳐 쓰지 말라는 뜻.)
- 문자열이 끊기면 작업하기 어렵고, 코드를 찾기 어려워집니다. - 문자열을 생성하는 경우 문자열 연결 대신 템플릿 문자열을 쓴다.
// bad
function sayHi(name) {
return 'How are you, ' + name + '?';
} // bad
function sayHi(name) {
return ['How are you, ', name, '?'].join();
} // bad
function sayHi(name) {
return `How are you, ${ name }?`;
} // good
function sayHi(name) {
return `How are you, ${name}?`;
}
- 절대로 문자열에
eval()
을 사용하지 마세요. 너무나 많은 취약점을 만듭니다. - 문자열에 불필요한 이스케이프 문자를 사용하지 마세요.
- 백슬래시는 가독성을 해치기 때문에 필요할 때만 사용해야 합니다.
// bad
const foo = '\'this\' \i\s \"quoted\"'; // good
const foo = '\'this\' is "quoted"';
const foo = `my name is '${name}'`;
3. 함수 (중요)
- 함수 선언식 대신 기명 함수 표현식을 사용합시다 (함수선언은 호이스트되므로….)
- 함수 이외의 불록(
if
,while
, 등)에서 함수를 선언하지 마세요. 브라우저는 이를 허용하겠지만, 모두 다르게 해석합니다. - ECMA-262 명세는
블록
을 구문의 일종으로 정의하고 있지만 함수선언은 구문이 아닙니다.
// bad
if (currentUser) {
function test() {
console.log('Nope.');
}
} // good
let test;
if (currentUser) {
test = () => {
console.log('Yup.');
};
}
- 함수의 인자를 변조하기 보다는 기본 매개변수 문법을 사용하세요.
// still bad
function handleThings(opts) {
if (opts === void 0) {
opts = {};
}
// ...
} function handleThings(opts = {}) {
// ...
}
- 절대로 매개변수를 바꾸지 마세요. (재할당도 x)
// bad(재할당)
function f1(obj) {
obj.key = 1;
} function f1(a) {
a = 1;
// ...
}
// good
function f3(a) {
const b = a || 1;
// ...
} function f4(a = 1) {
// ...
}
4. 화살표 함수(중요)
- 익명함수를 사용할 때는 화살표 함수 표현을 사용하세요.
- 화살표 함수는 그 컨텍스트의this
에서 실행하는 버전의 함수를 만듭니다. 이것은 보통 원하는대로 작동하고, 보다 간결합니다.
// bad
[1, 2, 3].map(function (x) {
const y = x + 1;
return x * y;
}); $(".go-main, .go-info1, .go-info3, .go-info4").on("click", function(e){
// ...
}); // good
[1, 2, 3].map((x) => {
const y = x + 1;
return x * y;
}); $(".go-main, .go-info1, .go-info3, .go-info4").on("click", (e) => { // ...
});
- 표현식이 여러 줄에 걸쳐 있을 때는 가독성을 높이기 위해 소괄호로 감싸주세요.
- 함수의 시작과 끝 부분을 알기 쉽게 해주기 때문입니다
// bad
['get', 'post', 'put'].map(httpMethod => Object.prototype.hasOwnProperty.call(
httpMagicObjectWithAVeryLongName,
httpMethod,
)
); // good
['get', 'post', 'put'].map(httpMethod => (
Object.prototype.hasOwnProperty.call(
httpMagicObjectWithAVeryLongName,
httpMethod,
)
));
- 항상 인자를 괄호로 감싸세요 (인자가 한 개 뿐이라도)
- 인자 추가, 제거시 변경사항이 최소화됩니다.
// bad
[1, 2, 3].map(x => x * x); // good
[1, 2, 3].map((x) => x * x);
- 암시적 반환을 하는 화살표 함수 몸체의 위치를 적절히 설정하세요.
// bad
(foo) =>
bar; (foo) =>
(bar); // good
(foo) => bar;
(foo) => (bar);
(foo) => (
bar
)
5. 제어문(중요)
- 만약
if
블록이 항상return
구문을 실행시킨다면,else
블록은 불필요합니다.return
을 포함한if
블록을 잇는else if
블록 안에return
구문이 있으면 여러if
블록으로 나눠질 수 있습니다.
// 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;
}
}
- 제어문 (
if
,while
등)이 너무 길거나 최대 길이를 넘긴 경우, 각 조건을 새로운 줄에 두세요. 논리 연산자는 줄의 시작부분에 있어야 합니다.
// bad
if ((foo === 123 || bar === 'abc') &&
doesItLookGoodWhenItBecomesThatLong() && isThisReallyHappening()) {
thing1();
}// bad
if (foo === 123 &&
bar === 'abc') {
thing1();
}// good
if (
(foo === 123 || bar === 'abc')
&& doesItLookGoodWhenItBecomesThatLong()
&& isThisReallyHappening()
) {
thing1();
}// good
if (foo === 123 && bar === 'abc') {
thing1();
}
let, const, function, class 선언을 포함하는 case
와default
구문 안에 블록을 만들 때는 괄호를 사용하세요
// 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 {}
}
}
6. 비구조화
- 하나의 객체에서 여러 속성에 접근할 때는 객체 비구조화를 사용하세요.
// 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}`;
}
- 여러 값을 반환하는 경우 배열 비구조화가 아닌 객체 비구조화를 사용하세요.
// bad
function processInput(input) {
// something...
return [left, right, top, bottom];
} // 반환되는 데이터의 순서를 생각해야합다
const [left, __, top] = processInput(input); // good
function processInput(input) {
// something...
return { left, right, top, bottom };
} // 필요한 데이터만 선택하면 됩니다
const { left, top } = processInput(input);
7. 호이스팅
var
선언은 할당없이 가장 가까운 함수 스코프의 꼭대기에 호이스트됩니다. const
와 let
선언은 Temporal Dead Zones (TDZ)라고 불리는 새로운 개념의 혜택을 받습니다. 왜 typeof는 더 이상 안전하지 않은가에 대해서 알고있는 것이 중요합니다.
// 인터프리터는 변수선언을 스코프의 선두에 호이스트합니다// 위의 예는 다음과 같이 다시 쓸수 있습니다: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;}