코드컨벤션

자바스크립트 중요 개념

참조


  • 모든 참조에는 var 대신 const를 쓰기 참조를 재할당 할수 없게 함으로써, 버그를 방지
  • 참조에 재할당을 해야하는 상황이면 let을 사용
  • const, let 모두 블록단위 스코프임에 유의

객체


  • 객체 생성시 리터럴 문법을 사용 객체 생성시 {} 를 사용하라는 뜻
  • 동적 속성을 갖는 객체는 속성 계산명을 사용 속성명이 바뀔수 있는 속성은 속성계산명 [Key]: value 을 사용
  • 메소드의 단축구문을 사용 속성과 값의 이름이 동일하면 속성이름만 적기
  • 단축구문을 사용한경우 객체의 최상단에 배치
  • 유효하지 않은 식별자에만 따옴표 속성 사용 일반적인 속성은 따옴표 없이 표기
  • hasOwnPropertypropertyIsEnumerableisPrototypeOf와 같은 Object.prototype 메소드를 직접 호출하지 말기 객체의 속성에 의해 메소드가 가려질수 있음
 
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));
 
  • 객체에 대한 얕은복사를 할 때는 Object.assign 대신 객체 전개 구문을 사용
  • 특정 속성이 생략된 새로운 개체를 가져올 때는 객체 나머지 연산자 사용 js에선 원본 객체가 손상되는 것을 최대한으로 지양한다

배열


  • 배열을 생성할떄 리터럴 구문을 사용 리터럴이라는 말이 계속 나오는데 정확한 뜻을 몰라서 찾아봄 JS용어
  • 배열에 직접 값을 할당하지 말고, Array#push 사용
  • 순회가능한 객체 (iterable object) 를 배열로 만들 때, Array.from 대신, … 구문을 사용 순회가능 객체가 뭐지? Iterable Object → (Array, String, Set, Map, …)
  • array-like 객체를 배열로 변환할 때, Array.from 사용 array-like가 뭐지? Array-Like → (length 속성과, 인덱싱(0,1,2,…)된 요소를 가진 객체)
  • 매핑할 때는 전개 구문 … 대신 Array.from 을 사용 중간 배열 생성을 방지
 *Array.from은 map에 비해 메모리는 적게쓰지만, 오래걸린다는 단점이 있음 [StackOverFlow](https://stackoverflow.com/questions/26052699/array-from-vs-array-prototype-map)*
  • 배열 메소드 콜백에는 리턴 구문 사용

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

  • 배열이 여러줄에 걸쳐 있다면 배열을 연 이후와 닫기 이전에 줄바꿈하기

비구조화


  • 하나의 객체에서 여러 속성에 접근할 때에는 객체 비구조화 사용 속성들을 위한 임시 참조를 만들지 않게 해주고, 객체에 반복적인 접근방지
  • 배열 비구조화 를 사용
  • 여러 값을 반환하는 경우 배열 비구조화 말고, 객체 비구조화 사용 배열 비구조화를 사용하려면 비구조화시 배열의 순서까지 고려해야하는 불편함이 있음

문자열


  • 문자열에는 작은 따옴표 사용
  • 100자가 넘는 문자열을 문자열 연결을 이용해 여러줄에 걸쳐 쓰지 말기 문자열이 끊어지면 작업하기 까다롭고, 찾기도 힘듬
  • 문자열을 생성하는 경우, 문자열 연결 대신, 템플릿 문자열 사용
  • 절대로 문자열에 eval() 사용하면 안됨, 너무나 많은 취약점을 만듦 eval is evil

  • 문자열에 불필요한 이스케이프 문자 사용 자제 가독성을 해침

함수


  • 함수선언식 말고 기명 함수표현식을 사용 함수 선언은 호이스팅 된다. 즉 함수가 선언되기 전에 함수를 참조하는것이 쉽다는 뜻 이는 유지보수에 어려움을 가져다 준다, 함수에 이름을 명시적으로 지정하면 디버깅 시 콜 스택에서 함수이름을 알 수 있다
  • 즉시 함수 표현식을 괄호로 감싸기 괄호로 감싸면 괄호 안의 표현을 명확하게 해줌
*즉시 함수 표현식에 방법은 여러 방법이 있지만 전체를 괄호로 묶는 방식을 사용하자*
*(function() {})() [X] (function() {}()) [O]*
  • 함수 이외의 블록(If, while, {}, 등)에서 함수를 선언하지 말기, 브라우저는 이를 허용하지만, 모두 다 다르게 해석한다

  • 참고 ECMA-262 명세는 블록 을 구문으로 명시하고 있지만 함수는 구문이 아님

표현식: 표현식은 값을 계산하고 반환합니다.
구문: 구문은 특정 작업을 수행하며, 프로그램의 흐름을 제어합니다.
[구문과 표현식](https://velog.io/@sangwook0613/Expression-%EA%B3%BC-Statement)
  • 절대 함수의 매개변수 이름을 arguments 로 지으면 안됨 함수 스코프에 전해지는 arguments 객체의 참조를 덮어씀

  • 절대 arguments 를 사용하지 말기, 차라리 나머지 문법 사용하기 … 을 사용하면 매개변수를 몇개 사용할지 확실히 할수 있고, 나머지 문법을 사용한것은 진짜 Array인것에 반해 arguments는 Array-Like 객체가 아니다

  • 함수의 인자를 변조하기 보다는 기본 매개변수 문법을 사용
*void 0 은 undefined 를 뜻한다,*
*void 0 == null: true, void 0 === null: false, void 0 == false: false*
  • 사이드 이펙트가 있을만한 기본 매개변수는 사용하지 않기 혼란을 야기
*사이드이펙트(부수효과): 하나의 동작에, 두개 이상의 효과를 가져다 주는 것이라고 이해했다
함수를 실행 → 전체 상태가 변화 (리액트)
함수를 실행 → 외부 변수의 값이 변화
값을 할당 → 다른 값도 변화*
 
*사이드 이펙트가 나쁜건 아니지만, 유지보수의 측면에서 순수함수 를 작성하는게 좋다고 한다
순수함수: 오직 함수의 입력만이 함수의 결과에 영향을 주는 함수*
  • 기본 매개변수는 항상 뒤쪽에 배치하기
  • 절대로 새로운 함수를 만들기 위해 함수 생성자를 사용하지 말 것 함수 생성자 쓰지마! (new Function ())

  • 함수 시그니처에 공백 넣기 function함수명(){}

  • 절대로 매개변수를 바꾸지 말기 C++ 에서 const로 변수를 선언하는것 처럼 매개변수 건들지 않기

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

  • 절대로 매개변수를 재할당하지 않기 매개변수를 재할당 하는것은 예측할 수 없는 결과를 불러 일으킵니다. 특히 arguments를 사용할때 말이죠 또한 V8에서 최적화 문제를 일으킬 수 있습니다
  • 가변인자 함수를 호출할 때는 전개 구문을 사용 그냥 하던대로 … 사용하면 됨

  • 여러 줄의 시그니처 또는 호출을 취하는 함수는 이 가이드에 있는 다른 것처럼 들여 쓰기를 해야함 한줄에 각 항목을 하나씩 두고, 마지막 항목에 쉼표를 넣는다

화살표 함수


  • 익명함수를 사용할 때에는 화살표 함수 표현을 사용
  • 하나의 식으로 구성된 함수가 사이드이펙트가 없는 표현식을 반환할 경우, 중괄호를 생략, 암시적 반환가능 그외의 경우는 중괄호도 사용하고, return도 사용할 것
  • 표현식이 여려 줄에 걸쳐 있을 때는 가독성을 높히기 위해 소괄호 사용
  • 명확성과 일관성을 위해 인자를 괄호로 감싸기 .map((x) ⇒ x _ x); [O].map(x ⇒ x _ x); [X]

  • 화살표 함수 구문을 비교연산자와 헷갈리지 않게 작성하기

  • 암시적 반환을 하는 화살표 함수의 몸체의 위치를 적절하게 설정하기

클래스 & 생성자


  • prototype 을 직접 조작하는 것은 피하고, 항상 class 을 사용
  • 상속에는 extends 를 사용 그냥 하던대로 하면 됨, 다른 방법도 있지만 그건 사용하지 않는다고 한다

  • 메소드가 this를 반환하게 함으로써 메소드 체이닝을 할 수 있음

  • toString() 을 사용해도 되지만, 올바르게 동작하는지와, 사이드 이펙트가 없는지 확인하기 음.. 근데 어지간하면 다른함수명 사용하자..
  • 클래스는 생성자가 명시되지 않은 경우 기본 생성자를 갖음 빈생성자 함수나, 부모 클래스로 위임하는 함수는 불필요함
  • 중복되는 클래스 멤버를 만들지 말기 하던대로 하면됨, 그냥 클래스 내에서 같은 이름 쓰지말라는 소리
  • 클래스 메소드는 this 를 사용하거나, 해당 메소드를 정적 메소드로 만들어야 함 생성한 클래스 인스턴스의 속성에 따라 클래스 메소드가 다르게 동작해야한다 (그동안 해오던 대로) this를 사용하지 않는 함수는 정적메소드로 빼라는뜻

모듈


  • 항상 모듈(import / export) 을 비표준 모듈 체계 대신 사용 쉽게 말해 require말고, import export 사용해라
  • 와일드 카드 import 는 쓰지 말기
  • import 문으로부터 바로 export 하지말기 한줄이 간편하긴 하지만, 명확한 import 와 명확한 export 를 통해 일관성을 얻을 수 있음
  • 같은 경로는 한 곳에 import 하기 같은 경로에서 하는 여러 줄의 import 는 유지보수를 힘들게 함
  • 가변 바인딩을 export 하지 말기 일반적으로 상수 참조(const)만 export 되어야 함
  • 한가지만 export 하는 모듈에서는 default export 사용하기
  • import 구문을 다른 구문들 위에 두기
  • 여러 줄에 걸친 import 는 들여쓰기 하기
  • 모듈 import 구문에 Webpack loader 구문 사용하지 말기 import 에서 Webpack 구문을 사용하면 이 코드가 모듈 번들러에 연결됨, loader 구문은 webpack.config.js 에서 사용
  • 자바스크립트 파일 확장자명을 명시하지 말기 리팩토링을 제한시킨다

이터레이터 & 제네레이터


  • 이터레이터를 사용하지 말기, for-in 이나 for-of 대신 자바스크립트의 고급함수 사용 고급함수는 불변 규칙을 적용한다. 사이드이펙트에 대해 추측하는것보다 순수함수를 다루는 것이 더 쉽다
*배열을 이터레이트할 때*  `map()` `every()`  `filter()`  `find()`  `findIndex()`  `reduce()`  `some()` 을 사용
배열을 생성할 때는 `Object.keys()` / `Object.values()` / `Object.entries()`를 사용
*개인적으로 가장 충격적이었던 사실..*
  • 당분간은 제네레이터 사용하지 말기 ES5로 트랜스파일이 잘 안됨 트랜스파일: 한 언어로 작성된 소스코드가 비슷한 수준의 추상화를 가진 다른언어로 변환하는 것

  • 만약 제네레이터를 사용할거면, 함수 시그니처의 공백이 적절한지 확인 *function*는 같은 개념의 키워드, function* 로 사용해야 적절함, function * [X]* 근데 쓰지 말라니까 걍 쓰지마

속성


  • 속성에 접근할 떄 마침표를 사용
  • 변수를 사용해서 속성에 접근할떄 [] 사용
  • **제곱 연산할 떄 제곱연산자 ** 사용**

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

변수


  • 변수를 선언할 때는 항상 constlet 만 사용 그렇지 않으면 전역 변수로 선언된다. 전역 스페이스를 오염시키지 않기를 바란다

  • 하나의 변수 선언 / 할당에는 하나의 constlet 을 사용 디버거로 선언을 단계별로 살펴볼 수 있다

  • const 를 그룹화한 다음 let 을 사용 const 먼저 쭉 쓰고 let 을 쓰라는 뜻
  • 필요한 곳에서 변수를 할당한되, 합당한 곳에 두기 let 과 const는 블록 스코프이지, 함수 스코프가 아님

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

  • 변수 할당 체이닝을 사용하지 않기 변수할당 체이닝은 암시 전역변수를 만든다
  • 단항 증감 연산자를 사용하지 말기 오류를 일으킬 수 있고, num += 1과 같은 구문으로 값을 변경하는것이 ++, -- 구문을 사용하는것보다 의미있는 일이라고 생각된다

이것도 좀 충격적이네

  • 값을 할당할 때 = 앞 뒤에서 줄 바꿈하지 말기 할당하는 값의 길이가 길어질 경우 값을 괄호로 둘러싸기
  • 사용하지 않는 변수 남겨두지 말기

호이스팅


  • let과 const 는 Temporal Dead Zones (TDZ)이라고 불리는 새로운 개념의 혜택을 받음 var는 가장 가까운 함수스코프 꼭대기에 호이스팅 되는다는데 (안쓸거니까 알 필요없다)
  • 익명 함수의 경우 함수가 할당되기 전의 변수가 호이스트 됨
  • 명명 함수의 경우도 똑같이 변수가 호이스트되고, 함수의 이름이나 본체는 호이스트 되지 않음
  • 함수 선언은 함수의 이름과 본체가 호이스트 됨

비교 연산자


  • ”==”, “!=” 대신 ”=", "! 사용
  • if문 과 같은 조건식은 ToBoolean 메소드에 의해 강제형변환이 되어 항상 다음과 같은 규칙을 따름
  • *Objecttrue로 평가*
  • *Undefinedfalse로 평가*
  • *Nullfalse로 평가*
  • *Booleansboolean형의 값으로 평가*
  • *Numberstrue로 평가, 하지만 +0, -0, Nan의 경우 false로 평가*
  • *Stringtrue로 평가, 하지만 ‘’false로 평가*
  • Boolean 비교는 단축형을 사용, 단 숫자나 문자열은 명시적으로 비교
  • 렉시컬 선언(let, const, function, class) 을 포함하는 switch 문 안에 블록을 만들 떄 괄호 사용하기
  • 삼항 연산자를 중첩해서는, 안되며 일반적으로 한줄로 표현
  • 불필요한 삼항 연산자는 사용하지 말기 어지간하면 삼항 연산자는 사용하는걸 피하자
  • 연산자를 섞어 사용할 때 해당 연산자들을 괄호로 둘러싸기 코드가 더 읽기쉬우지고, 개발자의 의도가 명확해짐

블록


  • 여러 줄의 블록에는 중괄호를 사용 해오던대로 하면 됨
  • 여러줄의 if 와 else 문을 사용 할때에는, else 를 if 블록의 닫는 중괄호와 같은 줄에 두기
  • if 블록이 항상 return 구문을 실행한다면 else 블록은 불필요함 if 블록을 잇는 else if 문에 return 구문이 있으면 여러 if 문으로 나누어질 수 있음

제어문


  • 제어문(if, while)이 너무 긴 경우, 각 조건을 새로운 줄에 두기. 논리 연산자는 줄의 시작부분에 와야함
  • 선택연산자를 제어구문대신 쓰지 말기

주석


  • **여러 줄에 걸쳐 주석을 작성할 때에는 /** … \*/ 을 사용하기**
  • 한 줄 주석을 사용 할때에는 // 를 사용하기. 주석 전에는 빈행을 넣기
  • 모든 주석은 공백으로 시작해야함
  • 문제를 지적하거나 재고를 요구하는 경우, 주석 앞에 FIXME, TODO 를 붙임 다른 개발자에게 빠른 이해를 도울 수 있음

  • 문제에 대한 주석은 // FIXME: 사용

  • 문제의 해결책에 대한 주석은 // TODO: 사용

공백


  • 탭은 공백문자 두개로 작성하기 난 지금까지 4칸으로 썼는데 2칸으로 줄여야겠다
  • 주요 중괄호 앞에는 공백문자 한개 넣기
  • 제어문 (if, while) 의 소괄호 앞에는 공백 하나 넣기, 함수선언이나 호출시 인자앞 공백 넣지 말기 함수에서 사용하는 소괄호에는 공백넣지 말기 기억
  • 파일 끝에 개행문자 1개 넣기 그니까 파일 끝은 무조건 개행문자로만 끝나게 만들라는 뜻
  • 길게 메소드 체이닝하는 경우(2개이상) 들여쓰기를 하기, 그리고 마침표를 맨 앞에 두기
  • 구문의 앞과 블록의 뒤에는 빈 행을 두기
  • 블록에 빈행을 끼워 넣지 말기 그냥 블록에서 컴팩트하게 적으라는 거 같다
  • 여러 빈행을 두지 않기 깔끔해 보이려고 빈행을 억지로 넣지 말아라
  • 소괄호 안쪽에 공백 두지 않기
  • 대괄호 안쪽에 공백 두지 않기
  • 중괄호 안쪽에는 공백 두기
  • 한 줄에 코드가 100자 넘는것은 피하기 (공백포함) 긴문자열인 경우는 예외 (문자열 길다고 분리해서 쓰면 안됨)
  • 쉼표 이전에는 공백넣지말고, 이후에 공백넣기 하던대로 하면됨

  • 계산된 속성 내에서는 공백을 넣으세요

 *eslint: [`computed-property-spacing`](https://eslint.org/docs/rules/computed-property-spacing)*
 
 - `*"never"` (default) disallows spaces inside computed property brackets\*
 - `*"always"` requires one or more spaces inside computed property brackets\*
 
 *이 말이 애매해서 찾아봤는데 그냥 `“never”`을 사용하라는 뜻인듯 싶다*
  • 함수 호출할떄 공백 넣지 말기
  • 객체 리터럴 속성의 키와 값 사이에는 공백 넣기
  • 행의 마지막에 공백 남겨놓지 말기
  • 여러 빈행을 쓰지 말기, 파일의 맨앞에 빈행 쓰지 말기 파일 끝에는 마지막행에는 빈행 하나두기

쉼표


  • 쉼표는 항상 뒤에 나머지요소 (…args) 뒤에는 쉼표가 없다

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

세미콜론


  • 세미콜론 쓰자 하던대로 하면된다

형변환 강제


  • 구문의 선두에서 형 강제를 하자
  • 문자열 String 으로 형변환 시키자 원시타입에 new를 붙여서 초기화하면 Object가 된다, new 붙이지 말기
  • 숫자를 형 변환하는 경우 Number를 사용하고, parseInt를 사용하는 경우 기수도 명시를 해줘야 함 10진수로 변환의 경우, Number(numStr) 이나 parseInt(numStr, 10) 를 사용하라는 뜻
  • 어떤 이유에서인지 parseInt가 병목현상을 일으켜 성능상의 이슈로 비트 시프트를 사용해야하는 경우 하려고했던 것을 왜(why)와 무엇을(what) 주석으로 남겨라
  • 주의: 비트연산자를 사용하는경우, 숫자는 64비트로 표현되어 있으나, 비트시프트를 사용하는경우 32비트 정수로 넘겨짐 따라서 숫자가 32비트 이상 넘어가면 예기치못한 현상을 야기할수 있음
  • 불리언

명명 규칙


  • 한 문자로 된 이름은 피해라 이름으로부터 의도가 읽혀질수 있도록 해라
  • 객체, 함수, 인스턴스에는 캐멀케이스(camelCase)를 사용
  • 클래스나 생성자에는 파스칼케이스(PascalCase)를 사용
  • 언더스코어를 사용하지 마라 자바스크립트는 속성이나 메소드 측면에서 은닉된 정보라는 개념을 갖고 있지않다. 언더스코어는 일반적으로 “private” 을 의미하지만 자바스크립트에서 해당 속성은 완전히 public하다. 요약 자바스크립트에서 뭔가 private하게 사용하고싶다면, 그것을 불가능하다
  • 참조에 this를 저장하지 말기 화살표 함수나, Function#bind 사용

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
  • 파일 이름은 default export의 이름과 일치해야 함 대문자든 소문자든간에 파일이름은 default export의 이름과 일치해야한다
  • 함수를 export default할 때 캐멀케이스 사용하기, 파일이름과 함수이름은 같아야 함
  • 생성자 / 클래스 / 싱글톤 / 함수 라이브러리 / 단순 객체를 export 할 때에는 파스칼케이스 사용하기 헷갈릴만한데, export하는 객체의 경우는 파스칼케이스로 쓰라한다 / 일반적으로는 캐멀케이스
  • 두 문자어나 이니셜은 모두 대문자거나 소문자여야 함 이름은 가독성을 위한것이지, 컴퓨터 알고리즘을 위한 것이 아니다
  • 선택적으로 변수이름을 대문자들로 지을수 있음 대문자로 이름을 지을때는 언더스코어도 써도 되는거 같다
    • export일때
    • const일 때 모든 const 변수 이름을 대문자로 짓나요? - 이것은 필수사항이 아니며, 파일 내 상수 이름을 꼭 대문자로 지을 필요는 없습니다. 하지만 내보내기되는 상수 이름은 대문자로 지어야 합니다.
    • 프로그래머가 해당 변수와 그 속성이 변하지 않을것이라 확신할 때 내보내기 되는 객체 이름을 대문자로 짓나요? - 최상위 수준의 내보내기를 할 때 대문자로 이름짓고 (예시: EXPORTED_OBJECT.key) 모든 중첩된 속성이 변경되지 않도록 유지합니다.

접근자


  • 속성을 위한 접근자 함수는 필수가 아님
  • 자바스크립트의 getters/setters를 사용하지 마라 예기치 못한 사이드이펙트를 일으키고, 테스트와 유지보수를 힘들게 한다
  • 속성이나 메소드가 boolean이라면, isVal 이나 hasVal 을 사용
  • get(), set() 함수를 만들되, 일관성있게 만들기

이벤트


  • (DOM 이나 BackBone 이벤트같은) 이벤트로 payload 값을 넘기는 경우, raw 값보다, 객체리터럴 (해시값) 을 넘겨라 이후 contributors 들이 이벤트와 관련한 모든 이벤트 핸들러를 바꾸는 대신, 이벤트 payload의 값을 추가할 수 있다.

제이쿼리


  • 제이쿼리 객체 변수 앞에 $ 를 붙여라
  • 제이쿼리의 검색결과 를 캐시 쓸 때마다 호출해서 찾지말고, 찾은값을 변수에 담아놓으라는 뜻
  • DOM검색에는 $(’.sidebar ul’)이나 parent > child $(’.sidebar > ul’) 과 같은 캐스캐이딩을 사용
  • 한정된 제이쿼리 객체 춰리에서는 find 사용