Code convention: JavaScript

SNPLab Inc.
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. 변수, 참조

  • 변수를 선언할 때는 항상 constlet을 사용하세요. 이렇게 하지 않으면 전역 변수로 선언됩니다.
// 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;
}
  • letconst 는 둘 다 블록스코프라는 것을 유의하세요.
    - 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 선언을 포함하는 casedefault구문 안에 블록을 만들 때는 괄호를 사용하세요
// 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 선언은 할당없이 가장 가까운 함수 스코프의 꼭대기에 호이스트됩니다. constlet 선언은 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;}

--

--