//변수 및 함수이름: camelcase(첫글자 소문자, 단위로 첫글자 대문자, _사용 금지)
//숫자, 문자, boolean
let helloThere = 3;
const heyYeji = 5;
//배열: 배열은 복수형이름
const dogs = [];
//정규표현식-정규표현식은 'r'로 시작
const rDesc = /.*/;
//함수
function getPropertyName() {
//some code...
}
//이벤트 핸들러-'on'으로 시작
const onClick = () => {};
const onKeyDown = () => {};
//불린 반환 함수 - 반환 값이 불린이면 'is'로 시작
let isAvailabale = false;
//지역변수 or private 변수명은 '_'로 시작한다
let _privateVariableName;
//URL, HTML과 같은 범용적인 대문자 약어는 대문자 그대로 사용
parseHTML
parseXML
// 전역 변수를 사용하지 않는다: 전역변수는 window에 로딩되어서, 모든 부분에서 접근할 수 있기 때문에 위험
// Bad
function sum(x, y) {
result = x + y;
return result;
}
// Bad
function foo() {
let a = b = 0; // let a = (b = 0);와 같다. b가 암묵적 전역이 된다.
}
// Good
function sum(x, y) {
let result = x + y;
return result;
}
// Good
function foo() {
let a, b;
a = b = 0;
}
//상수는 영어 대문자 스네이크 표기법(_사용) 사용
SYMBOLIC_CONSTANTS;
//생성자는 대문자 카멜 케이스
class ConstructorName {
}
// 선언과 할당
//var 절대 사용하지 말 것
//값이 변하지 않는 변수는 const(가장 권장), 값이 변하는 변수는 let을 사용하여 선언
//const를 let보다 위에 선언한다. (그룹핑하여 가독성)
//const, let은 블록 스코프이므로 호이스팅 되지 않는다.
//const와 let은 사용시점에서 선언 및 할당한다.
// Bad - 블록 스코프 밖에서 변수 선언
function foo() {
const len = this._array.length;
let i = 0;
let j = 0;
let len2, item;
for (; i < len; i += 1) {
//...
}
len2 = this._array2.length;
for (j = 0, len2 = this._array2.length; j < len2; j += 1) {
item = this._array2[j];
//...
}
}
// Good
function foo() {
const len = this._array.length;
for (let i = 0; i < len; i += 1) {
//...
}
// 사용 시점에 선언 및 할당
const len2 = this._array2.length;
for (let j = 0; j < len2; j += 1) {
const item = this._array2[j];
//...
}
}
//배열과 객체
//배열과 객체는 리터럴로 선언(생성자보다 짧고 명확하여 실수를 줄일 수 있음)
// Bad-배열 생성자 사용
const emptyArr = new Array();
const arr = new Array(1, 2, 3, 4, 5);
// Bad - 객체 생성자 사용
const emptyObj = new Object();
const obj = new Object();
// Good
const emptyArr = [];
const arr = [1, 2, 3, 4, 5];
// Good
const emptyObj = {};
const obj = {
pro1: 'val1',
pro2: 'val2'
};
//배열 및 객체 복사시 순환문을 사용하지 않고, 전개 연산자를 사용하면 좀 더 명확하게 정의할 수 있다. (es5에서는 slice()사용)
//good
const items = [1, 2, 3];
const copyItems = [...items];
console.log(copyItems); //[1, 2, 3]
const objItem = {
one: 1,
two: 2,
three: 3
}
const copyObj = {
...objItem,
four: 4
}
console.log(copyObj); //one, two, three, four 모두가 들어옴
// Bad
for (i = 0; i < len; i++) {
itemsCopy[i] = items[i];
}
// 배열 요소 중 하나라도 줄바꿈이 있다면, 모든 요소는 일관되게 줄바꿈 해야한다.
const a = [1
]; //bad
const b = [
1
]; //good
const c = [1,
2, 3]; //bad
const d = [
1,
2,
3
]; //good
// 객체 프로퍼티가 한개인 경우에만 한줄 정의 허용하며, 2개 이상일때는 개행을 강제한다.
const obj = {foo: 'a', bar: 'b'}; //bad
//good
const obj = {
foo: 'a',
bar: 'b'
};
const obj = {foo: 'a'}; //good
const obj = {
foo: 'a', //good
}
// 객체 리터럴 정의 시 콜론 앞은 공백 허용x, 콜론 뒤는 항상 공백 강제
//bad
const obj = {
foo : 'a'
}
//good
const obj = {
foo: 'a'
}
//객체 내의 메소드 표현시, 축약 메소드 표기를 사용한다.
//bad
const atom = {
addValue: function(value) {
return 1;
}
}
//good
const atom = {
addValue(value) {
return 1;
}
}
//메소드 문법 사용시, 매소드 사이에 개행을 추가한다.
// Bad
class MyClass {
foo() {
//...
}
bar() {
//...
}
}
// Good
class MyClass {
foo() {
//...
}
bar() {
//...
}
}
//함수
//함수 생성자를 사용하여 선언하지 않는다(생성자 함수 쓰지 말라는 말 아님)
//bad
const doSomething = new Function('param1', 'param2', 'return param1 + param2;');
console.log(doSomething(1, 2)); //3
//good: 함수 선언식
function doSomething(parm1, parm2) {
return parm1 + parm2;
}
//good: 함수 표현식
const doSomething = function(parm1, parm2) {
return parm1 + parm2;
}
doSomething(1, 2); //3
//함수표현식을 사용한다면, 함수는 사용하기 전에 선언해야한다.
const sum = function(parm1, parm2) {
return parm1 + parm2;
}
const sumValue = sum(1, 2);
sumValue; //3
// 화살표 함수
//함수 표현식 대신, 화살표 함수를 사용한다.
// 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;
});
//화살표 함수의 파라미터 하나이면, 괄호 생략
// Good
[1, 2, 3].map(x => x * x);
// Good
[1, 2, 3].reduce((y, x) => x + y);
// 함수의 본체가 하나의 표현식이라면 중괄호를 생략하고, 암시적 반환을 사용할 수있다. 그외에는 return 명시
//bad
[1, 2, 3].map(num => {
const nextNum = num + 1;
`A string containt the ${nextNum}.`; //여기 return 해줘야함
})
//good
[1, 2, 3].map(number => `A string containing the ${number + 1}.`);
//암시적 반환을 사용할 경우, 함수 본문 전에 개행해지 않는다.
//bad
(foo) =>
bar;
//good
(foo) => bar
//Promise Executor 함수
//Destructuring (구조분해할당)
//오브젝트의 프로퍼티에 접근할 때는 destructuring을 이용한다 (✨객체의 경우, 반드시 key값과 같아야함)
const yeji = {
firstName: 'kim',
lastName: 'yeji'
}
//bad
function getFullName(user) {
const firstName = user.firstName;
const lastName = user.lastName;
return `${firstName} ${lastName}`;
}
//Good
function getFullName(obj) {
const {firstName, lastName} = obj; //obj에서 {firstName, lastName} key를 가져온다
return `${firstName} ${lastName}`;
}
//Good -> getFullName(yeji)로 하면, obj가 firstName, lastName으로 나뉘어짐
function getFullName({firstName, lastName}) {
return `${firstName} ${lastName}`;
}
//bad
const first = arr[0];
const second = arr[1];
//Good
const [first, second] = arr;
//새로운 이름으로 변수에 할당할때는 Destructuring을 사용하지 않아도 된다.
const changeFirstName = user.firstName;
const {firstName: changeFirstName} = user; //changeFirstName: firstName키값이 들어옴
// 템플릿 문자열: 변수 등을 조합해서 문자열을 생성하는 경우, 템플릿 문자열을 이용한다 (코드복잡도 낮아짐)
function sayHi(name) {
return `How are you, ${name}?`;
}
// 클래스와 생성자
// class, extends를 이용해서 객체 생성 및 상속 구현
// 모듈
// 항상 import, export를 이용해서 모듈을 로드한다.
import {es6} from './AirbnbStyleGuide';
export default es6;
//wildcard import는 사용하지 않는다
//import * from './text'; //bad
import * as AirbnbStyleGuide from './text';
//import문으로 직접 export하지 않는다 (간결하긴 하지만, import와 export 구분하는 것이 좋다)
export {es6 as default} from './airbnbStyleGuide'; //bad
// 블록 구문
// 한줄짜리 블록이라도 {}를 생략하지 않고, 명확히 줄바꿈 한다. (당장은 두줄 줄일수있지만, 생략하면 코드 구조를 애매하게 만들고, 잠재 위험요소)
// Bad
if(condition) doSomething();
// Bad
if (condition) doSomething();
else doAnything();
// Bad
for(let prop in object) someIterativeFn();
// Bad
while(condition) iterating += 1;
// Good
if (condition) {
//...
}
// Good
if (condition) {
//...
} else {
//...
}
// 키워드와 조건문 사이에 빈칸을 사용한다. 키워드와 조건문 사이가 빼곡하면 코드를 읽기 어렵다
// Bad
for(let i=0; i<100; i+=1) {
someIterativeFn();
}
// Good (가능하면 for of, for in)
for(let i = 0; i < 100; i += 1) {
someIterativeFn();
}
// do-while문 사용시, while문 끝에 세미콜론을 쓴다.
do {
//...
} while (condition);
// switch-case 사용시 첫번째 case문을 제외하고 case문 사용 이전에 개행한다.
// Good
switch (value) {
case 1:
doSomething1();
break;
case 2:
doSomething2();
break;
case 3:
return true;
default:
throw new Error('This shouldn\\'t happen.');
}
// switch-case 사용시 각 구문은 break, return, throw 중 한개로 끝나야 하며, default문이 없으면 '// no default' 표시 해주기
// 여러 케이스가 하나의 기능을 한다면 break 생략해도 좋지만, 조금이라도 다른 기능을 포함한다면 break를 생략하지 않고 다른 방식으로 수정
// Bad - 케이스 1 과 2 가 서로 다른 처리를 하지만 break가 생략됨
switch (value) {
case 1:
doSomething1();
case 2:
doSomething2();
break;
case 3:
return true;
// no default
}
// Bad - default문이 없지만 아무런 표기가 없음
switch (value) {
case 1:
doSomething1();
break;
case 2:
doSomething2();
break;
case 3:
return true;
}
// Good - 여러 케이스가 하나의 처리를 할 때는 break생략 허용
switch (value) {
case 1:
case 2:
doSomething();
break;
case 3:
return true;
// no default
}
// 조건 확인하기
// 함중 등호 연산자인 ===, !==만 사용한다. ==, !=는 암묵적 캐스팅으로인한 버그로 이어진다.
// 반환 하기
// 함수 내에서 반환은 한번만 한다. (예측 가능, 간결한 함수 작성)
// 특정 값을 반환해야하는경우 함수 맨 마지막에서 한번만 반환하며, 만약 예외로 빠져나가는 경우는 제외한다.
// return문 바로 위는 한칸 비워놓는다. (다른 명령과 return 붙어있으면 가독성 좋지 않음)
// Bad
function getResult() {
if (condition) {
return someDataInTrue;
}
return someDataInFalse;
}
// Allow
function foo(isValid) {
// 예외처리로 바로 빠져나감
if (!isValid) {
return;
}
//...
return someDataInTrue;
}
// Good
function getResult() {
let resultData;
//...
if (condition) {
//...
resultData = someDataInTrue;
} else {
//...
resultData = someDataInFalse;
}
return resultData;
}
// 순회 하기
// 반복문 사용은 일반화된 순회 메소드(map, forEach...) 사용을 권장한다. (실수 가능성이 적다)
// 주석
// 설명하려는 구문에 맞춰 들여쓰기
// 문장 끝에 주석 작성할 경우, 한 줄 주석을 사용하며 공백을 추가한다.
// Bad
var someValue = data1;//주석 표시 전후 공백
// Bad
var someValue = data1; /* 여러 줄 주석 */
// Good
var someValue = data1; // 주석 표시 전후 공백
// 여러줄 주석을 할때는 *의 들여쓰기 맞춘다. 첫줄 및 마지막 줄을 비운다.
/*
* 주석 내용
*/
// 코드 블럭 주석 처리를 위해서는 한줄 주석 사용하기 (* 주석 bad)
// const tmp = 3;
// 공백
// 키워드, 연산자와 다른 코드 사이에 공백이 있어야 한다.
// Bad
var value;
if(typeof str==='string') {
value=(a+b);
}
// Good
var value;
if (typeof str === 'string') {
value = (a + b);
}
// 시작 괄호 바로 다음, 끝 괄호 바로 이전에 공백이 있으면 안된다
// Bad - 괄호 안에 공백
if ( typeof str === 'string' )
// Bad - 괄호 안 공백
var arr = [ 1, 2, 3, 4 ];
// Good
if (typeof str === 'string') {
//...
}
// Good
var arr = [1, 2, 3, 4];
// 콤마 다음에 값이 오면 공백이 있어야한다. (콤마로 구분된 아이템간의 간격)
let arr = [1,2,3,4]; //bad
let arr = [1, 2, 3, 4]; //good