어제에 이어 에어비앤비 스타일 가이드 학습하기
문자열에는 작은 따옴표(``) 를 사용하자.
// bad
const name = "Capt. Janeway";
// bad - template literals should contain interpolation or newlines
const name = `Capt. Janeway`;
// good
const name = 'Capt. Janeway';
문자열 작성할 때 템플릿 리터럴로 사용할 때가 종종 있었는데 권장되는 방식이 아니였다니...!
문자열 연결은 템플릿 리터럴을 사용하자.
// 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}?`;
}
+
로 연결하는 방식은 학부생때 자바 배울 때 종종 봤던 거라 거부감은 없었지만 읽기가 헷갈리는 경우가 많았었다. 배열 형태로 만들어서 join 시키는 방법은 생각치못했지만 몰라도 되는 방법이였다.
템플릿 문자열 사용할때 가끔 ${ name }
처럼 사이에 공백을 넣어서 사용할 때도 있었는데 이게 bad한 거였다니..또르르 나름 눈에 잘 띄어서 좋다고 생각했는데 아니였나봅니다.
함수 선언식보다 함수 표현식을 사용하자.
// bad
function foo() {
// ...
}
// bad
const foo = function () {
// ...
};
// good
// 변수 참조 호출과 구분되는 이름
const short = function longUniqueMoreDescriptiveLexicalFoo() {
// ...
};
선언식 함수가 호이스팅 된다는 점 때문에 좋아해서 자주 사용했다. 개인적으로 표현식보다 선언식을 더 좋아는 이유중 하나였는데.. 그거때문에 권장하지 않는다고 한다.
함수는 변수처럼 위에서부터 하나씩 착착착 쓰는거보다 함수는 아래로 쭉 빼서 정의 해놓고 위에서 꺼내쓰는걸 선호했었는데 선언식 함수보다 표현식
을 권장한다니 너무 슬프더 ㅠㅠㅠㅠ..
이제 에어비앤비 컨벤션을 따라야 한다면 보내줘야 하는 건가...ㅋㅋㅋ
표현식 함수를 명시적으로 작명해줘야 한다는 점도 놀라웠다. 디버깅에 더 좋으니 그렇게 사용하라는 것 같다.
변수명만 정의하고 무명으로 사용해도 되지 않을까? 싶었는데 이 부분은 정말.. 내 코드 스타일과 너무나도 상반됐다. ㅋㅋㅋㅋ
그냥 화살표 함수를 사용하는 게 좋겠다..
함수 이외의 블록에서 함수를 선언하지 말 것.
예를 들면 if나 while문에서 함수를 선언하는 것이 있을 수 있다.
// bad
if (currentUser) {
function test() {
console.log('Nope.');
}
}
// good
let test;
if (currentUser) {
test = () => {
console.log('Yup.');
};
}
오.. if문 내부에서는 화살표 함수를 사용해야 하는 건가보다. test 변수가 if문 바깥에 선언되어 있는데 if문 내부에서 함수로 정의해주어도 상관이 없나보다.
함수 인자를 변경하지 말 것.
// really bad
function handleThings(opts) {
opts = opts || {};
// ...
}
// still bad
function handleThings(opts) {
if (opts === void 0) {
opts = {};
}
// ...
}
// good
function handleThings(opts = {}) {
// ...
}
default로 작성해주는 게 더 좋구나.
함수 매개인자가 비어있는 경우 함수 내부에서 고쳐쓰지 말라는 것 같다.
함수 생성자를 사용하지 않기
// bad
var add = new Function('a', 'b', 'return a + b');
// still bad
var subtract = Function('a', 'b', 'return a - b');
함수 생성자.. 엄청 생소하다.
이렇게 작성하는 사람은 아직까지 못봤는데.
함수 시그니처에 공백 넣기
// bad
const f = function(){};
const g = function (){};
const h = function() {};
// good
const x = function () {};
const y = function a() {};
매개 변수를 변경하지 않기
// bad
function f1(obj) {
obj.key = 1;
}
// good
function f2(obj) {
const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1;
}
매개변수 객체를 변경하면 사이드 이펙트가 발생할 수 있다.
const obj = {
name: "아이유"
};
console.log(obj); // {name: '아이유'}
const test = (obj) => {
obj.name = "IU";
};
test(obj);
console.log(obj); // {name: 'IU'}
오브젝트와 같이 레퍼런스 변수들은 함수 내부에서 변경하지 않도록 주의!
매개 변수를 재할당 하지 말자
최적화 문제도 있을 수 있구나..
가끔 한번씩 했던 짓이라 조심해야겠다. ㅋㅋㅋㅋ
// 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) {
// ...
}
아예 새로운 변수를 만들어서 할당하거나, default 값을 사용해서 해결할 수 있는 경우엔 defult를 사용하도록 하자.
가변 인자 함수에는
...
를 사용하자.
// bad
const x = [1, 2, 3, 4, 5];
console.log.apply(console, x);
// good
const x = [1, 2, 3, 4, 5];
console.log(...x);
// bad
new (Function.prototype.bind.apply(Date, [null, 2016, 8, 5]));
// good
new Date(...[2016, 8, 5]);
매개 변수가 여러줄 일 때
// bad
function foo(bar,
baz,
quux) {
// ...
}
// good
function foo(
bar,
baz,
quux,
) {
// ...
}
// bad
console.log(foo,
bar,
baz);
// good
console.log(
foo,
bar,
baz,
);
1번 function은 너무 생긴거부터 불편하게 생겼다...
근데 마지막 매개변수에 콤마를 넣는 건 처음보네.
보통 오브젝트 key : value, key : value 할때나 마지막 콤마 넣을지 안넣을지 취향에 따라 갈린다고 생각했는데..
매개 변수도 마지막에 콤마를 넣얼 수 있다니.. 저렇게 써도 에러가 안 나는구나..ㅋㅋㅋ
아무튼 이 코드의 핵심은 들여쓰기가 같이 들어가야 된다는 것이다!
자바스크립트 초반에 화살표 함수 보고 이 이상하게 생긴건 어떻게 쓰는거지..? 했던 기억이 있다.
지금은 언제 그랬냐는 듯이 정말 너무 잘쓰는중. 마치 스프레드 연산자처럼..
익명 함수를 사용할 때는 화살표 함수를
// 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;
});
this
를 알기에도 좋기 때문에 화살표 함수가 권장되는 경우가 많은 것 같다.
// 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) {
}
}
let bool = false;
// bad
foo(() => bool = true);
// good
foo(() => {
bool = true;
});
리턴을 명시하냐, 괄호를 쓰냐에 대한 코드 스타일인듯하다.
명확성, 일관성 유지를 위해서 인자는 괄호로 감싸는 것을 권장하고 있다.
드디어 올 것이 왔구나..
클래스 울렁증이 있어서 클래스랑 친해지기 힘들었는데ㅠㅠ
prototype을 직접 조작하는 것을 피하자.
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;
}
}
prototype으로 추가하는게 익숙해서 자료구조 공부할 때 저렇게 짰었는데 사실 연관된 하나라고 생각하면 class가 더 구조화가 잘 되어있는 것은 사실이긴 하다.
다만 this
가 꼴보기 싫을 때가 많을뿐..ㅜ
상속할 때는
extends
// 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];
}
}
생성자 함수를 상속하는 코드는 처음봤다.
오.. 저렇게 사용하는구나 보기에도 쓰기 싫게 생기긴 했다.
클래스의 메소드가 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);
와 this 반환하면 체이닝 할 수 있다는 점을 왜 모르고 있었지 ㅋㅋㅋㅋ
이건 알고 있으면 나중에 써볼 일이 있을 것 같다.
this
를 사용하지 않으면static
으로 선언 해서 정적 메소드임을 표기하자.
// bad
class Foo {
bar() {
console.log('bar');
}
}
// good
class Foo {
bar() {
console.log(this.bar);
}
}
// good
class Foo {
constructor() {
// ...
}
}
// good
class Foo {
static bar() {
console.log('bar');
}
}
this가 사용되지 않으면 static 키워드를 사용해주면 되는구나.. 오앙..
단순히 인스턴스 안 만들고 사용할 때만 static을 사용해주면 된다 정도만 알고 있었는데 this와도 연관이 있을 수 있다는 것을 알게되었다.
오호 코딩 스타일에 관심이 많으신가 봐욤^^ 이틀 연속으로 코드 스타일에 대해서 올리셨네욤^^
항상 열심히 하는 모습 보기 좋습니다.