Skip to content

Latest commit

 

History

History
2622 lines (2028 loc) · 67 KB

STYLE_GUIDE.md

File metadata and controls

2622 lines (2028 loc) · 67 KB

PC-COMMUNICATION JavaScript Style Guide

PC-COMMUNICATION 자바스크립트 스타일 가이드는 Airbnb 자바스크립트 스타일 가이드Naver 자바스크립트 스타일 가이드 를 기준으로 작성되었습니다.

Table of Contents

  1. Types
  2. References
  3. Objects
  4. Arrays
  5. Destructuring
  6. Strings
  7. Functions
  8. Arrow Functions
  9. Classes & Constructors
  10. Modules
  11. Iterators and Generators
  12. Properties
  13. Variables
  14. Hoisting
  15. Comparison Operators & Equality
  16. Blocks
  17. Comments
  18. Whitespace
  19. Commas
  20. Semicolons
  21. Type Casting & Coercion
  22. Naming Conventions
  23. Accessors
  24. Events
  25. jQuery
  26. Resources

Types

Airbnb 와 동일합니다.

  • 1.1 Primitives: primitive type은 그 값을 직접 조작한다.

    • string
    • number
    • boolean
    • null
    • undefined
    const foo = 1;
    let bar = foo;
    
    bar = 9;
    
    console.log(foo, bar); // => 1, 9
  • 1.2 Complex: 참조형(Complex)은 참조를 통해 값을 조작한다.

    • object
    • array
    • function
    const foo = [1, 2];
    const bar = foo;
    
    bar[0] = 9;
    
    console.log(foo[0], bar[0]); // => 9, 9

⬆ back to top

References

Airbnb 와 동일합니다.

  • 2.1 변수 선언은 가급적 const 를 사용하고, var 를 사용하지 않는다. eslint: prefer-const, no-const-assign

    // bad
    var a = 1;
    var b = 2;
    
    // good
    const a = 1;
    const b = 2;
  • 2.2 참조를 재할당 해야한다면 var 대신 let 을 사용한다. eslint: no-var jscs: disallowVar

    // bad
    var count = 1;
    if (true) {
      count += 1;
    }
    
    // good, use the let.
    let count = 1;
    if (true) {
      count += 1;
    }
  • 2.3 letconst 는 선언된 블록 안에서만 존재하는 블록 스코프이다.

    // const 와 let 은 선언된 블록의 안에서만 존재한다.
    {
      let a = 1;
      const b = 1;
    }
    console.log(a); // ReferenceError
    console.log(b); // ReferenceError

⬆ back to top

Objects

3.6 항목을 제외하고는 Airbnb 와 동일합니다.
(3.6 항목은 Naver 와 동일합니다.)

  • 3.1 오브젝트를 작성할 때는, 리터럴 구문을 사용한다. eslint: no-new-object

    // bad
    const item = new Object();
    
    // good
    const item = {};
  • 3.2 동적 프로퍼티명을 갖는 오브젝트를 작성할 때, 계산된 프로퍼티명(computed property names)을 이용한다.

    function getKey(k) {
      return `key named ${k}`;
    }
    
    // bad
    const obj = {
      id: 5,
      name: "San Francisco",
    };
    obj[getKey("enabled")] = true;
    
    // good
    const obj = {
      id: 5,
      name: "San Francisco",
      [getKey("enabled")]: true
    };
  • 3.3 메서드의 단축 구문을 이용한다. eslint: object-shorthand

    // bad
    const atom = {
      value: 1,
    
      addValue: function (value) {
        return atom.value + value;
      },
    };
    
    // good
    const atom = {
      value: 1,
    
      addValue(value) {
        return atom.value + value;
      },
    };
  • 3.4 속성의 단축구문을 이용한다. eslint: object-shorthand

    const lukeSkywalker = "Luke Skywalker";
    
    // bad
    const obj = {
      lukeSkywalker: lukeSkywalker,
    };
    
    // good
    const obj = {
      lukeSkywalker,
    };
  • 3.5 속성의 단축 구문은 오브젝트 선언의 시작 부분에 그룹화한다.

    const anakinSkywalker = "Anakin Skywalker";
    const lukeSkywalker = "Luke Skywalker";
    
    // bad
    const obj = {
      episodeOne: 1,
      twoJediWalkIntoACantina: 2,
      lukeSkywalker,
      episodeThree: 3,
      mayTheFourth: 4,
      anakinSkywalker,
    };
    
    // good
    const obj = {
      // 단축 속성 구문 - 시작
      lukeSkywalker,
      anakinSkywalker,
      // 단축 속성 구문 - 끝
      episodeOne: 1,
      twoJediWalkIntoACantina: 2,
      episodeThree: 3,
      mayTheFourth: 4,
    };
  • 3.6 속성명이 키워드(default, if, ...)일 경우에는 꼭 따옴표를 붙인다. 또한, -문자와 같이 속성명으로 지정할수 없는 경우에는 꼭 따옴표를 붙인다. eslint: quote-props

    // bad
    const bad = {
      foo: 3,
      default: 20,
      data-blah: 5
    };
    
    // good
    const good = {
      foo: 3,
      "default": 20,
      "data-blah": 5,
      10: "naver"
    };
  • 3.7 hasOwnProperty, propertyIsEnumerable, isPrototypeOf 와 같은 Object.prototype 메서드를 직접적으로 사용하지 않는다. eslint: no-prototype-builtins

    // bad
    console.log(object.hasOwnProperty(key));
    
    // good
    console.log(Object.prototype.hasOwnProperty.call(object, key));
    
    // best
    const has = Object.prototype.hasOwnProperty; // 모듈스코프에서 한 번 캐시하세요.
    /* or */
    import has from "has";
    // ...
    console.log(has.call(object, key));
  • 3.8 얕은 복사(shallow-copy)를 하기 위해서 Object.assign 보다는 spread 연산자(...)를 선호한다. 오브젝트에서 몇몇 속성을 제거한 새로운 오브젝트를 얻고자 할때는 rest 파라미터(...)를 사용한다.

    // very bad
    const original = { a: 1, b: 2 };
    const copy = Object.assign(original, { c: 3 }); // this mutates `original`
    delete copy.a; // so does this
    
    // bad
    const original = { a: 1, b: 2 };
    const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 }
    
    // good
    const original = { a: 1, b: 2 };
    const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 }
    
    const { a, ...noA } = copy; // noA => { b: 2, c: 3 }

⬆ back to top

Arrays

4.7 항목을 제외하고는 Airbnb 와 동일합니다.

  • 4.1 배열을 작성 할 때는 리터럴 구문을 사용한다. eslint: no-array-constructor

    // bad
    const items = new Array();
    // good
    const items = [];
  • 4.2 아이템을 배열에 추가하는 경우, 직접 배열에 항목을 대입하지 말고 Array#push 를 이용한다.

    const someStack = [];
    
    // bad
    someStack[someStack.length] = "abracadabra";
    
    // good
    someStack.push("abracadabra");
  • 4.3 배열을 복사할 때는 배열의 spread 연산자(...) 를 이용한다.

    // bad
    const len = items.length;
    const itemsCopy = [];
    let i;
    
    for (i = 0; i < len; i++) {
      itemsCopy[i] = items[i];
    }
    
    // good
    const itemsCopy = [...items];
  • 4.4 순회 가능한 객체(iterable object)를 배열로 변환할 때는 Array.from 대신 spread 연산자(...) 를 사용하세요.
    Naver 에서는 array-like 오브젝트를 배열로 변환하는 경우에 대해서 별도로 가이드 하지 않는다.

    const foo = document.querySelectorAll('.foo');
    
    // good
    const nodes = Array.from(foo);
    
    // best
    const nodes = [...foo];
  • 4.5 array-like 객체를 배열로 변환할 때는 Array.from을 사용하세요.
    Naver 에서는 Array.from에 대해 별도로 가이드 하지 않는다.

    const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 };
    
    // bad
    const arr = Array.prototype.slice.call(arrLike);
    
    // good
    const arr = Array.from(arrLike);
  • 4.6 매핑할 때는 전개 구문 ... 대신 Array.from을 사용하세요. 중간 배열 생성을 방지하기 때문입니다.
    Naver 에서는 Array.from에 대해 별도로 가이드 하지 않는다.

    // bad
    const baz = [...foo].map(bar);
    
    // good
    const baz = Array.from(foo, bar);
  • 4.7 Airbnb 와 다르게 배열의 메서드 콜백에 대해서는 별도로 가이드 하지 않는다. eslint: array-callback-return

  • 4.8 배열이 멀티 라인인 경우, 배열의 시작(before)과 끝(after)은 개행한다.

    // bad
    const arr = [
      [0, 1], [2, 3], [4, 5],
    ];
    
    const objectInArray = [{
      id: 1,
    }, {
      id: 2,
    }];
    
    const numberInArray = [
      1, 2,
    ];
    
    // good
    const arr = [[0, 1], [2, 3], [4, 5]];
    
    const objectInArray = [
      {
        id: 1,
      },
      {
        id: 2,
      },
    ];
    
    const numberInArray = [
      1,
      2,
    ];

⬆ back to top

Destructuring

Airbnb 와 동일합니다.
Naver 에선 비구조화에 대해 별도의 가이드를 제공하지 않습니다.

  • 5.1 하나의 객체에서 여러 속성에 접근할 때는 객체 비구조화를 사용하세요. eslint: prefer-destructuring

    왜? 비구조화는 속성들을 위한 임시 참조를 만들지 않도록 해주고, 객체의 반복적인 접근을 방지합니다. 반복적인 객체 접근은 중복 코드와 실수를 만들어내고, 더 많은 코드를 읽게 합니다. 또한 객체 비구조화는 블록에서 사용되는 객체의 구조를 정의하는 단일한 위치를 제공함으로써 어떤 것이 사용되는지 알아내기 위해 모든 블록을 읽지 않아도 되도록 해줍니다.

    // 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}`;
    }

  • 5.2 배열 비구조화를 사용하세요. eslint: prefer-destructuring

    const arr = [1, 2, 3, 4];
    
    // bad
    const first = arr[0];
    const second = arr[1];
    
    // good
    const [first, second] = arr;

  • 5.3 여러 값을 반환하는 경우 배열 비구조화가 아닌 객체 비구조화를 사용하세요.

    왜? 이렇게 하면 이후 호출처에 영향을 주지 않고 새로운 속성을 추가하거나 순서를 변경할 수 있습니다.

    // bad
    function processInput(input) {
      // 기적이 일어납니다
      return [left, right, top, bottom];
    }
    
    // 반환되는 데이터의 순서를 생각해야합다
    const [left, __, top] = processInput(input);
    
    // good
    function processInput(input) {
      // 기적이 일어납니다
      return { left, right, top, bottom };
    }
    
    // 필요한 데이터만 선택하면 됩니다
    const { left, top } = processInput(input);

⬆ back to top

Strings

Airbnb 와 동일합니다.
6.1 항목은 Naver 에선 쌍따옴표("")를 권장합니다.
6.2 항목은 Naver 에선 + 연산자를 권장합니다.

  • 6.1 문자열에는 작은 따옴표 ''를 사용하세요. eslint: quotes

    // bad
    const name = "Capt. Janeway";
    
    // bad - template literals should contain interpolation or newlines
    const name = `Capt. Janeway`;
    
    // good
    const name = 'Capt. Janeway';

  • 6.2 100자가 넘는 문자열을 문자열 연결을 이용해 여러 줄에 걸쳐 쓰지 마세요.

    왜? 문자열이 끊어지면 작업하기 어렵고, 코드를 찾기 어렵게 됩니다.

    // bad
    const errorMessage = 'This is a super long error that was thrown because \
    of Batman. When you stop to think about how Batman had anything to do \
    with this, you would get nowhere \
    fast.';
    
    // bad
    const errorMessage = 'This is a super long error that was thrown because ' +
      'of Batman. When you stop to think about how Batman had anything to do ' +
      'with this, you would get nowhere fast.';
    
    // good
    const errorMessage = 'This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.';
  • 6.3 프로그램에서 문자열을 생성하는 경우는 문자열 연결이 아닌 template strings를 이용한다. eslint: prefer-template template-curly-spacing

    // bad
    function sayHi(name) {
      return "How are you, " + name + "?";
    }
    
    // bad
    function sayHi(name) {
      return ["How are you, ", name, "?"].join();
    }
    
    // good
    function sayHi(name) {
      return `How are you, ${name}?`;
    }
  • 6.4 절대로 eval() 을 사용하지 않는다.

  • 6.5 문자열에 불필요한 escape 문자를 사용하지 않는다. eslint: no-useless-escape

    // bad
    const foo = "\'this\' \i\s \'quoted\'";
    
    // good
    const foo = "\"this\" is 'quoted'";
    const foo = `my name is '${name}'`;

⬆ back to top

Functions

7.1 ~ 2, 7.11 ~ 14 항목을 제외하고는 Airbnb 와 동일합니다.

  • 7.1 함수 표현식 대신 함수 선언문을 사용한다. eslint: func-style
    Airbnb 에선 함수 표현식 권장.
    Naver 에선 별도의 스타일 가이드 제공하지 않음.

    왜? 함수 스타일에 대해서는 별도의 스타일 가이드를 제공하지 않는다.

    1. 함수선언문은 코드를 구현한 위치와 관계없이 자바스크립트의 특징인 호이스팅에 따라 브라우저가 자바스크립트를 해석할 때 맨 위로 끌어 올려진다. 함수표현식은 함수선언문과 달리 선언과 호출 순서에 따라서 정상적으로 함수가 실행되지 않을 수 있다.
    2. 함수 표현식에 Typescript (React.FC) 사용 시, Default Props 정상동작하지 않음 (React 공식문서도 선언문 이용)
    // bad
    const foo = function() {
      // ...
    };
    
    // bad
    // foo 변수만 호이스팅 됨.
    const foo = function bar() {
      // ...
    };
    
    // good
    function foo() {
      // ...
    }
  • 7.2 즉시 실행함수는 함수를 괄호로 감싼다. eslint: wrap-iife

    // bad
    !function()) {
      console.log("Welcome to the Internet. Please follow me.");
    }();
    
    // bad
    (function() {
      console.log("Welcome to the Internet. Please follow me.");
    }());
    
    // good
    (function() {
      console.log("Welcome to the Internet. Please follow me.");
    })();
  • 7.3 함수 이외의 블록 (if나 while같은) 안에서 함수를 선언하지 않는다. eslint: no-loop-func

    // bad
    let i;
    for (i = 10; i; i--) {
        (function() { 
          return i; 
        })();
    }
    
    // bad
    while(i) {
        let a = function() {
          return i;
        };
        a();
    }
    
    // good
    const a = function() {};
    let i;
    for (i = 10; i; i--) {
        a();
    }
  • 7.4 Airbnb 와 다르게 block 내의 함수선언에 대해서는 별도로 가이드 하지 않는다.

  • 7.5 절대로 파라미터에 arguments 를 지정하지 않는다. 이것은 함수 스코프에 전해지는 arguments 오브젝트의 참조를 덮어 버린다.

    // bad
    function nope(name, options, arguments) {
      // ...stuff...
    }
    
    // good
    function yup(name, options, args) {
      // ...stuff...
    }
  • 7.6 절대 arguments 를 이용하지 않는다. 대신에 rest 파라미터(...) 를 이용한다. eslint: prefer-rest-params

    // bad
    function concatenateAll() {
      const args = Array.prototype.slice.call(arguments);
      return args.join("");
    }
    
    // good
    function concatenateAll(...args) {
      return args.join("");
    }
  • 7.7 함수의 파라미터를 재정의하지 않는다. 대신 default 파라미터를 이용한다.

    // really bad
    function handleThings(opts) {
      opts = opts || {};
      // ...
    }
    
    // still bad
    function handleThings(opts) {
      if (opts === void 0) {
        opts = {};
      }
      // ...
    }
    
    // good
    function handleThings(opts = {}) {
      // ...
    }
  • 7.8 side effect 를 유발하는 default 파라미터의 이용을 피한다.

    var b = 1;
    // bad
    function count(a = b++) {
      console.log(a);
    }
    count();  // 1
    count();  // 2
    count(3); // 3
    count();  // 3
  • 7.9 항상 default 파라미터는 뒤쪽에 둔다.

    // bad
    function handleThings(opts = {}, name) {
      // ...
    }
    
    // good
    function handleThings(name, opts = {}) {
      // ...
    }
  • 7.10 절대 새 함수를 작성하기 위해 Function constructor를 이용하지 않는다. eslint: no-new-func

    // bad
    var add = new Function("a", "b", "return a + b");
    
    // still bad
    var subtract = Function("a", "b", "return a - b");
  • 7.11 익명함수는 function과 괄호 사이에 공백이 없다. 기명 함수(named function)는 함수 이름과 괄호 사이에 공백이 없다.
    async arrow function인 경우 async와 arrow function 사이에 공백이 있다.
    eslint: space-before-function-paren space-before-blocks

    // bad
    const f = function () {};
    const g = function a (){};
    const h = async(v,i) => {};
    
    // good
    const x = function() {};
    const y = function a() {};
    const z = async (v,i) => {};
  • 7.12 가급적 mutate parameter는 사용하지 않는다. 하지만, 필요에 의해서는 주의하여 사용한다. eslint: no-param-reassign

    // 권장하지 않음.
    function f1(obj) {
      obj.key = 1;
    }
  • 7.13 파라미터를 재할당하지 않는다. 단, 파라미터의 속성에 대해서는 재할당이 가능하다. eslint: no-param-reassign

    // bad
    function f1(a) {
      a = 1;
      // ...
    }
    
    // bad
    function f2(a) {
      if (!a) { a = 1; }
      // ...
    }
    
    
    // good
    function f3(a) {
      const b = a || 1;
      // ...
    }
    
    // good
    function f4(a) {
      if (!a) { a.b = 1; }
      // ...
    }    
  • 7.14 가변함수를 호출할 때는 spread 연산자 (...)를 사용한다. eslint: prefer-spread

    // 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]);
  • 7.15 함수의 정의가 멀티라인 인 경우, 오브젝트와 같은 스타일 가이드를 따른다. 19.1을 참조한다.

    // bad
    function foo(bar,
                 baz,
                 quux) {
      // ...
    }
    
    // good
    function foo(
      bar,
      baz,
      quux,
    ) {
      // ...
    }
    
    // bad
    console.log(foo,
      bar,
      baz);
    
    // good
    console.log(
      foo,
      bar,
      baz,
    );

⬆ back to top

Arrow Functions

8.2, 8.4 항목을 제외하고는 Airbnb 와 동일합니다.

  • 8.1 익명함수를 전달하는 경우, arrow function 표기를 이용한다. eslint: prefer-arrow-callback, arrow-spacing

    // 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;
    });
  • 8.2 함수의 몸체(body)가 단일 표현식이라면 중괄호({})를 생략하고, 묵시적으로 그 값은 반환값이 된다. 그렇지 않으면, 중괄호({})는 생략할 수 없고, 반환값이 필요한 경우는 return 을 명시한다. eslint: arrow-parens, arrow-body-style

    // 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,
    }));
    
    // good
    [1, 2, 3].forEach(number => {
      console.log(nextNumber);
    });
  • 8.3 식이 복수행에 걸쳐 있을 경우는 가독성을 더욱 좋게하기 위해 소괄호(())로 감싼다.

      // bad
      ['get', 'post', 'put'].map(httpMethod => Object.prototype.hasOwnProperty.call(
          httpMagicObjectWithAVeryLongName,
          httpMethod,
        )
      );
    
      // good
      ['get', 'post', 'put'].map(httpMethod => (
        Object.prototype.hasOwnProperty.call(
          httpMagicObjectWithAVeryLongName,
          httpMethod,
        )
      ));
  • 8.4 함수가 단일 파라미터인 경우, 소괄호(())는 생략한다. eslint: arrow-parens

    // bad
    [1, 2, 3].map((x) => x * x);
    
    // good
    [1, 2, 3].map(x => x * x);
    
    // good
    [1, 2, 3].map(number => (
      `A long string with the ${number}. It’s so long that we don’t want it to take up space on the .map line!`
    ));
    
    // bad
    [1, 2, 3].map((x) => {
      const y = x + 1;
      return x * y;
    });
    
    // good
    [1, 2, 3].map(x => {
      const y = x + 1;
      return x * y;
    });
  • 8.5 arrow function 문법(=>)과 비교 연산자 (<=, >=)를 함께 사용할 경우, 소괄호(())를 이용하여 혼란스럽지 않도록 표현한다. eslint: no-confusing-arrow

    // bad
    const itemHeight = item => item.height > 256 ? item.largeSize : item.smallSize;
    
    // bad
    const itemHeight = (item) => item.height > 256 ? item.largeSize : item.smallSize;
    
    // good
    const itemHeight = item => (item.height > 256 ? item.largeSize : item.smallSize);
    
    // good
    const itemHeight = (item) => {
      const { height, largeSize, smallSize } = item;
      return height > 256 ? largeSize : smallSize;
    };

⬆ back to top

Classes & Constructors

Airbnb 와 동일합니다.

  • 9.1 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;
      }
    }
  • 9.2 상속은 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];
      }
    }
  • 9.3 필요하다면, 메서드의 반환값으로 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);
  • 9.4 toString()을 작성하는 것을 허용하지만 올바르게 동작하는 지와 side effect 가 없는지를 꼭 확인한다.

    class Jedi {
      constructor(options = {}) {
        this.name = options.name || "no name";
      }
    
      getName() {
        return this.name;
      }
    
      toString() {
        return `Jedi - ${this.getName()}`;
      }
    }
  • 9.5 불필요한 빈 default constructor는 사용하지 않는다. eslint: no-useless-constructor

    // bad
    class Jedi {
      constructor() {}
    
      getName() {
        return this.name;
      }
    }
    
    // bad
    class Rey extends Jedi {
      constructor(...args) {
        super(...args);
      }
    }
    
    // good
    class Rey extends Jedi {
      constructor(...args) {
        super(...args);
        this.name = 'Rey';
      }
    }
  • 9.6 클래스에는 동일 멤버가 있어서는 안된다. eslint: no-dupe-class-members

    // bad
    class Foo {
      bar() { return 1; }
      bar() { return 2; }
    }
    
    // good
    class Foo {
      bar() { return 1; }
    }
    
    // good
    class Foo {
      bar() { return 2; }
    }

⬆ back to top

Modules

10.5, 10.9 항목을 제외하고는 Airbnb 와 동일합니다.

  • 10.1 비표준 모듈시스템이 아닌 (import/export) 를 항상 사용한다.

    // bad
    const AirbnbStyleGuide = require("./AirbnbStyleGuide");
    module.exports = AirbnbStyleGuide.es6;
    
    // ok
    import AirbnbStyleGuide from "./AirbnbStyleGuide";
    export default AirbnbStyleGuide.es6;
    
    // best
    import {es6} from "./AirbnbStyleGuide";
    export default es6;
  • 10.2 wildcard import 는 이용하지 않는다.

    // bad
    import * as AirbnbStyleGuide from "./AirbnbStyleGuide";
    
    // good
    import AirbnbStyleGuide from "./AirbnbStyleGuide";
  • 10.3 import 문으로부터 직접 export 하지 않는다.

    왜? 한줄이 간결하기는 하지만, 명확한 import와 명확한 export를 통해 일관성을 가질 수 있기 때문입니다.

    // bad
    // filename es6.js
    export {es6 as default} from "./airbnbStyleGuide";
    
    // good
    // filename es6.js
    import {es6} from "./AirbnbStyleGuide";
    export default es6;
  • 10.4 import는 중복되지 않게 한 곳에서 import 한다. eslint: no-duplicate-imports

    // bad
    import foo from "foo";
    // … some other imports … //
    import {named1, named2} from "foo";
    
    // good
    import foo, {named1, named2} from "foo";
    
    // good
    import foo, {
      named1,
      named2
    } from "foo";
  • 10.5 mutable 객체를 export 하는 것에 대해 강제하지 않는다. eslint: import/no-mutable-exports

    // good
    // let은 변경 가능한 객체
    let foo = {
      a: 10
    }
    export {foo};
    
    // good
    // const는 변경 가능하지 않는 객체
    const foo = 3;
    export {foo};
  • 10.6 export가 하나일 경우, default export를 사용한다. eslint: import/prefer-default-export

    // bad
    export function foo() {}
    
    // good
    export default function foo() {}
  • 10.7 모든 import문은 상위에 위치한다. eslint: import/first

    // bad
    import foo from "foo";
    foo.init();
    
    import bar from "bar";
    
    // good
    import foo from "foo";
    import bar from "bar";
    
    foo.init();
  • 10.8 멀티 라인 imports 문은 배열이나 오브젝트의 literal과 같이 표현한다. 19.1을 참조한다.

    // good
    import {
      longNameA,
      longNameB,
      longNameC,
      longNameD,
      longNameE,
    } from "path";
  • 10.9 웹팩 로더 문법 사용에 대해 강제하지 않는다. eslint: import/no-webpack-loader-syntax

    // good
    import fooSass from 'css!sass!foo.scss';
    import barCss from 'style!css!bar.css';
    
    // good
    import fooSass from 'foo.scss';
    import barCss from 'bar.css';

⬆ back to top

Iterators and Generators

Airbnb 와 다르게 별도의 가이드를 제공하지 않습니다.

Properties

Airbnb 와 동일합니다.

  • 12.1 프로퍼티에 억세스하는 경우는 점 . 을 사용한다. eslint: dot-notation

    const luke = {
      jedi: true,
      age: 28,
    };
    
    // bad
    const isJedi = luke["jedi"];
    
    // good
    const isJedi = luke.jedi;
  • 12.2 변수를 사용해 프로퍼티에 억세스하는 경우는 대괄호([])를 사용한다.

    const luke = {
      jedi: true,
      age: 28,
    };
    
    function getProp(prop) {
      return luke[prop];
    }
    
    const isJedi = getProp("jedi");

⬆ back to top

Variables

13.6 항목을 제외하고는 Airbnb 와 동일합니다.

  • 13.1 변수를 선언 할 때는 가급적 constlet을 사용한다. 그렇게 하지 않으면 글로벌 변수로 선언된다. eslint: no-undef prefer-const

    // bad
    superPower = new SuperPower();
    
    // good
    const superPower = new SuperPower();
  • 13.2 변수 선언은 변수당 하나씩 사용한다. eslint: one-var

    // bad
    const items = getItems(),
        goSportsTeam = true,
        dragonball = "z";
    
    // bad
    // (compare to above, and try to spot the mistake)
    const items = getItems(),
        goSportsTeam = true;
        dragonball = "z";
    
    // good
    const items = getItems();
    const goSportsTeam = true;
    const dragonball = "z";
  • 13.3 우선 const 를 그룹화하고 다음에 let 을 그룹화 한다.

    // bad
    let i, len, dragonball,
        items = getItems(),
        goSportsTeam = true;
    
    // bad
    let i;
    const items = getItems();
    let dragonball;
    const goSportsTeam = true;
    let len;
    
    // good
    const goSportsTeam = true;
    const items = getItems();
    let dragonball;
    let i;
    let length;
  • 13.4 letconst을 사용할 때는 블럭 스코프 이기 때문에, 변수가 사용될 적당한 위치에 변수를 선언한다.
    Naver 에선 letconst를 사용할 수 없다면, var로 상단에 변수를 선언한다.

    // bad - unnecessary function call
    function checkName(hasName) {
      const name = getName();
    
      if (hasName === 'test') {
          return false;
      }
    
      if (name === 'test') {
          this.setName('');
          return false;
      }
    
      return name;
    }
    
    // good
    function checkName(hasName) {
      if (hasName === 'test') {
          return false;
      }
    
      const name = getName();
    
      if (name === 'test') {
          this.setName('');
          return false;
      }
    
      return name;
    }
  • 13.5 여러 개의 변수를 한 줄에 동일한 값으로 설정하지 않는다. eslint no-multi-assign

    // bad
    (function example() {
      let a = b = c = 1;
    }());
    
    // good
    (function example() {
      let a = 1;
      let b = a;
      let c = a;
    }());
  • 13.6 ++, -- 연산자 사용이 가능하다. 연산자와 피연산자 사이에 공백을 두지 않는다. eslint no-plusplus

    // bad
    ++ i;
    i ++;
    
    // good
    ++i;
    i++;

⬆ back to top

Hoisting

Airbnb 와 동일합니다.

  • 14.1 var 선언은 할당 없이 스코프의 선두에 hoist 된다. constlet 선언은Temporal Dead Zones (TDZ) 라고 불리는 새로운 컨셉의 혜택을 받고 있다.

    // notDefined 가 글로벌변수에 존재하지 않는다고 판정한 경우, 잘 동작하지 않는다.
    function example() {
      console.log(notDefined); // => throws a ReferenceError
    }
    
    // 그 변수를 참조하는 코드의 뒤에서 그 변수를 선언한 경우
    // 변수가 hoist 된 상태에서 동작한다.
    // 주의:`true` 라는 값 자체는 hoist 되지 않는다.
    function example() {
      console.log(declaredButNotAssigned); // => undefined
      var declaredButNotAssigned = true;
    }
    
    // 인터프리터는 변수선언을 스코프의 선두에 hoist 한다.
    // 위의 예는 다음과 같이 다시 쓸수 있다.
    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;
    }
  • 14.2 익명 함수의 경우 함수가 할당되기 전의 변수가 hoist 된다.

    function example() {
      console.log(anonymous); // => undefined
    
      anonymous(); // => TypeError anonymous is not a function
    
      var anonymous = function() {
        console.log('anonymous function expression');
      };
    }
  • 14.3 기명 함수(named function)의 경우도 똑같이 변수가 hoist 된다. 함수명이나 함수본체는 hoist 되지 않는다.

    function example() {
      console.log(named); // => undefined
    
      named(); // => TypeError named is not a function
    
      superPower(); // => ReferenceError superPower is not defined
    
      var named = function superPower() {
        console.log('Flying');
      };
    }
    
    // 함수명과 변수명이 같은 경우도 같은 현상이 발생합니다.
    function example() {
      console.log(named); // => undefined
    
      named(); // => TypeError named is not a function
    
      var named = function named() {
        console.log("named");
      }
    }
  • 14.4 함수선언은 함수명과 함수본체가 hoist 된다.

    function example() {
      superPower(); // => Flying
    
      function superPower() {
        console.log("Flying");
      }
    }

⬆ back to top

Comparison Operators & Equality

Airbnb 와 동일합니다.

  • 15.1 == 이나 != 보다 ===!== 을 사용한다.

  • 15.2 if 문과 같은 조건식은 ToBoolean 메서드에 의한 강제형변환으로 평가되어 항상 다음과 같은 심플한 룰을 따른다.

    • Objecttrue 로 평가된다.
    • undefinedfalse 로 평가된다.
    • nullfalse 로 평가된다.
    • Boolanboolean형의 값 으로 평가된다.
    • Numbertrue 로 평가된다. 하지만 +0, -0, or NaN 의 경우는 false 이다.
    • Stringtrue 로 평가된다. 하지만 빈문자 "" 의 경우는 false 이다.
    if ([0]) {
      // true
      // 배열은 오브젝트이므로 true 로 평가된다.
    }
  • 15.3 Boolen에 대해서는 단축형을 사용한다.

    // bad
    if (name !== "") {
      // ...stuff...
    }
    
    // good
    if (name) {
      // ...stuff...
    }
    
    // bad
    if (collection.length > 0) {
      // ...stuff...
    }
    
    // good
    if (collection.length) {
      // ...stuff...
    }
  • 15.4 비교에 대한 자세한 정보는 Truth Equality and JavaScript by Angus Croll. 을 참조한다.

  • 15.5 case, default 구문에서 let, const, function, class가 사용 되는 경우에는 중괄호({})를 사용한다. eslint rules: no-case-declarations.

    // 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 {}
      }
    }
  • 15.6 중첩 3항 연산자는 사용하지 않는다. eslint rules: no-nested-ternary.

    // bad
    const foo = maybe1 > maybe2
      ? "bar"
      : value1 > value2 ? "baz" : null;
    
    // better
    const maybeNull = value1 > value2 ? "baz" : null;
    
    const foo = maybe1 > maybe2
      ? "bar"
      : maybeNull;
    
    // best
    const maybeNull = value1 > value2 ? "baz" : null;
    
    const foo = maybe1 > maybe2 ? "bar" : maybeNull;
  • 15.7 불필요한 3항 연산자는 사용하지 않는다. eslint rules: no-unneeded-ternary.

    // bad
    const foo = a ? a : b;
    const bar = c ? true : false;
    const baz = c ? false : true;
    
    // good
    const foo = a || b;
    const bar = !!c;
    const baz = !c;

⬆ back to top

Blocks

Naver 와 동일합니다.

  • 16.1 중괄호({})는 클래스, 메서드, 제어문의 블럭을 구분한다. 중괄호는 클래스 선언, 메서드 선언, 조건/반복문/제어문,줄의 마지막에서 시작한다.

    // bad
    const Empty = function()
    {
    }
    
    // good
    const Empty = function() {
    }
    
    switch (type) {
      case 0:
        break;
      case 1: {
        break;
      }
      default:
        common();
    }
    
    if (true) {
      return;
    } else if (false) {
      return;
    } else {
    }
  • 16.2 조건/반복문/제어문에 중괄호 사용한다. 조건/반복문/제어문이 한줄로 끝이라도 중괄호를 활용한다. eslint: brace-style

    // bad
    if (exp == null) return false;
    for (var i in obj) if ( i === "key" ) return obj[i];
    
    // good
    if (exp == null) {
      return false;
    }
    
    for (var i in obj) {
      if ( i === "stop" ) {
        return obj[i];
      }
    }

⬆ back to top

Comments

17.1, 17.2 항목을 제외하고 Airbnb 와 동일합니다.

  • 17.1 복수행의 코멘트는 /** ... */ 을 사용한다.
    함수일 경우 설명과 모든 파라미터, 반환값에 대해 형이나 값을 필수로 기술한다.

    // bad
    // make() returns a new element
    // based on the passed in tag name
    //
    // @param {String} tag
    // @return {Element} element
    function make(tag) {
    
      // ...stuff...
    
      return element;
    }
    
    // good
    /**
     * make() returns a new element
     * based on the passed in tag name
     *
     * @param {String} tag
     * @return {Element} element
     */
    function make(tag) {
    
      // ...stuff...
    
      return element;
    }
  • 17.2 단일행 코멘트에는 // 을 사용한다. 코멘트를 추가하고 싶은 코드의 상부에 배치한다.
    또한, 코멘트의 앞에 공백을 넣고 구문의 앞에 빈행을 남겨둔다.

    // bad
    const active = true;  // is current tab
    
    // good
    // is current tab
    const active = true;
    
    // bad
    function getType() {
      console.log("fetching type...");
      // set the default type to "no type"
      const type = this._type || "no type";
    
      return type;
    }
    
    // good
    function getType() {
      console.log("fetching type...");
    
      // set the default type to "no type"
      const type = this._type || "no type";
    
      return type;
    }
    
    // also good
    function getType() {
      // set the default type to "no type"
      const type = this._type || "no type";
    
      return type;
    }
  • 17.3 문제를 지적하고 재고를 촉구하는 경우나 문제의 해결책을 제안하는 경우 등, 코멘트의 앞에 FIXMETODO 를 붙이는 것으로 다른 개발자가 빠르게 이해할 수 있도록 한다. 이런 것들은 어떤 액션을 따른다는 의미이다. 액션이라는 것은 FIXME -- 해결이 필요 또는 TODO -- 구현이 필요 를 뜻한다.

  • 17.4 문제의 해결이 필요하다는 주석으로써 // FIXME: 를 사용한다.

    class Calculator extends Abacus {
      constructor() {
        super();
    
        // FIXME: total은 글로벌 변수를 사용해야한다.
        total = 0;
      }
    }
  • 17.5 구현이 필요하다는 주석으로 // TODO: 를 사용한다.

    class Calculator extends Abacus {
      constructor() {
        super();
    
        // TODO: total 은 옵션 파라미터로 설정해야한다.
        this.total = 0;
      }
    }

⬆ back to top

Whitespace

18. 11 ~ 13 항목을 제외하고는 Airbnb 와 동일합니다.

  • 18.1 탭은 공백문자 2개로 설정한다. eslint: indent
    Naver 에선 다른 방식으로 사용한다.

    // bad
    function foo() {
    ∙∙∙∙let name;
    }
    
    // bad
    function bar() {
    ∙let name;
    }
    
    // good
    function baz() {
    ∙∙let name;
    }
  • 18.2 주요 중괄호 ({}) 앞에는 공백을 1개 넣는다. eslint: space-before-blocks

    // bad
    function test(){
      console.log("test");
    }
    
    // good
    function test() {
      console.log("test");
    }
    
    // bad
    dog.set("attr",{
      age: "1 year",
      breed: "Bernese Mountain Dog",
    });
    
    // good
    dog.set("attr", {
      age: "1 year",
      breed: "Bernese Mountain Dog",
    });
  • 18.3 제어구문 (if 문이나 while 문 등) 의 소괄호(()) 앞에는 공백을 1개 넣는다. 함수선언이나 함수호출시 인수리스트의 앞에는 공백을 넣지 않는다. eslint: keyword-spacing

    // bad
    if(isJedi) {
      fight ();
    }
    
    // good
    if (isJedi) {
      fight();
    }
    
    // bad
    function fight () {
      console.log ("Swooosh!");
    }
    
    // good
    function fight() {
      console.log("Swooosh!");
    }
  • 18.4 연산자 사이에는 공백을 넣는다. eslint: space-infix-ops

    // bad
    const x=y+5;
    
    // good
    const x = y + 5;
  • 18.5 파일 끝에는 개행문자를 1개 넣는다. eslint: eol-last

    // bad
    (function(global) {
      // ...stuff...
    })(this);
    // bad
    (function(global) {
      // ...stuff...
    })(this);
    
    // good
    (function(global) {
      // ...stuff...
    })(this);
  • 18.6 메서드 체인이 2개를 초과한 경우, 적절히 줄 바꿈을 하여 사용한다. 또한 해당 줄이 새로운 구문이 아니라 메소드 호출임을 강조하는 마침표를 맨 앞에 둔다. 줄 바꿈 후에는 가독성을 위하여 자동 들여쓰기를 한다. eslint: newline-per-chained-call no-whitespace-before-property

    // bad
    $("#items").find(".selected").highlight().end().find(".open").updateCount();
    
    // bad
    $("#items").
      find(".selected").
        highlight().
        end().
      find(".open").
        updateCount();
    
    // good
    $("#items")
      .find(".selected")
        .highlight()
        .end()
      .find(".open")
        .updateCount();
    
    // bad
    const leds = stage.selectAll(".led").data(data).enter().append("svg:svg").classed("led", true)
        .attr("width", (radius + margin) * 2).append("svg:g")
        .attr("transform", `translate(${radius + margin},${radius + margin})`)
        .call(tron.led);
    
    // good
    const leds = stage.selectAll(".led")
        .data(data)
      .enter().append("svg:svg")
        .classed("led", true)
        .attr("width", (radius + margin) * 2)
      .append("svg:g")
        .attr("transform", `translate(${radius + margin},${radius + margin})`)
        .call(tron.led);
    
    // good
    const leds = stage.selectAll(".led").data(data);
  • 18.7 구문의 앞과 블록의 뒤에는 빈행을 남겨둔다.

    // bad
    if (foo) {
      return bar;
    }
    return baz;
    
    // good
    if (foo) {
      return bar;
    }
    
    return baz;
    
    // bad
    const obj = {
      foo() {
      },
      bar() {
      },
    };
    return obj;
    
    // good
    const obj = {
      foo() {
      },
    
      bar() {
      },
    };
    
    return obj;
    
    // bad
    const arr = [
      function foo() {
      },
      function bar() {
      },
    ];
    return arr;
    
    // good
    const arr = [
      function foo() {
      },
    
      function bar() {
      },
    ];
    
    return arr;
  • 18.8 블록에 빈행을 끼워 넣지 않는다. eslint: padded-blocks

    // bad
    function bar() {
    
      console.log(foo);
    
    }
    
    // also bad
    if (baz) {
    
      console.log(qux);
    } else {
      console.log(foo);
    
    }
    
    // good
    function bar() {
      console.log(foo);
    }
    
    // good
    if (baz) {
      console.log(qux);
    } else {
      console.log(foo);
    }
  • 18.9 소괄호(())의 안쪽에 공백을 추가하지 않는다. eslint: space-in-parens

    // bad
    function bar( foo ) {
      return foo;
    }
    
    // good
    function bar(foo) {
      return foo;
    }
    
    // bad
    if ( foo ) {
      console.log(foo);
    }
    
    // good
    if (foo) {
      console.log(foo);
    }
  • 18.10 대괄호([])의 안쪽에 공백을 추가하지 않는다. eslint: array-bracket-spacing

    // bad
    const foo = [ 1, 2, 3 ];
    console.log(foo[ 0 ]);
    
    // good
    const foo = [1, 2, 3];
    console.log(foo[0]);
  • 18.11 괄호 안에 공백을 삽입하지 않는다. eslint: object-curly-spacing

    // bad
    var obj = { };
    var obj = { "a": 2 };
    var arr = [ ];
    var arr = [ 1, 2 ];
    function foo( a, b ) {
    
    }
    
    // good
    var obj = {};
    var obj = {"a": 2};
    var arr = [];
    var arr = [1, 2];
    function foo(a, b) {
    
    }
  • 18.12 최대 줄 너비는 100 이다. 고해상도 모니터(해상도 1280*1024)사용이 보편화 됨에 따라, 최대 줄 사용 너비는 100자까지 가능하다. eslint: max-len

    // bad
    const foo = jsonData && jsonData.foo && jsonData.foo.bar && jsonData.foo.bar.baz && jsonData.foo.bar.baz.quux && jsonData.foo.bar.baz.quux.xyzzy;
    
    // bad
    $.ajax({ method: "POST", url: "https://www.naver.com/", data: { name: "John" } }).done(() => console.log("Congratulations!")).fail(() => console.log("You have failed this city."));
    
    // good
    const foo = jsonData &&
      jsonData.foo &&
      jsonData.foo.bar &&
      jsonData.foo.bar.baz &&
      jsonData.foo.bar.baz.quux &&
      jsonData.foo.bar.baz.quux.xyzzy;
  • 18.13 연산식의 경우에는 연산자 후에 줄 바꿈을 한다. 상위 레벨의 깊이에 맞게 들여쓰기를 한다

    // bad
    const sum = 100 + 200 + 300 
    + 400 + 500 + 600 + 700 + 800;
    
    // good
    const sum = 100 + 200 + 300 + 
         400 + 500 + 600 + 700 + 800;

⬆ back to top

Commas

Airbnb 와 동일합니다.

  • 19.1 콤마는 뒤에 표기한다. eslint: comma-style

    // bad
    const story = [
        once
      , upon
      , aTime
    ];
    
    // good
    const story = [
      once,
      upon,
      aTime,
    ];
    
    // bad
    const hero = {
        firstName: "Ada"
      , lastName: "Lovelace"
      , birthYear: 1815
      , superPower: "computers"
    };
    
    // good
    const hero = {
      firstName: "Ada",
      lastName: "Lovelace",
      birthYear: 1815,
      superPower: "computers"
    };
  • 19.2 끝에 콤마를 넣는다. eslint: comma-dangle

    // bad - git diff without trailing comma
    const hero = {
         firstName: "Florence",
    -    lastName: "Nightingale"
    +    lastName: "Nightingale",
    +    inventorOf: ["coxcomb graph", "modern nursing"]
    };
    
    // good - git diff with trailing comma
    const hero = {
         firstName: "Florence",
         lastName: "Nightingale",
    +    inventorOf: ["coxcomb chart", "modern nursing"],
    };
    
    // bad
    const hero = {
      firstName: "Dana",
      lastName: "Scully"
    };
    
    const heroes = [
      "Batman",
      "Superman"
    ];
    
    // good
    const hero = {
      firstName: "Dana",
      lastName: "Scully",
    };
    
    const heroes = [
      "Batman",
      "Superman",
    ];

⬆ back to top

Semicolons

Airbnb 와 동일합니다.

  • 20.1 ;은 문장의 끝에 표기한다. eslint: semi

    // bad
    (function() {
      const name = "Skywalker"
      return name
    })()
    
    // good
    (() => {
      const name = "Skywalker";
      return name;
    })();
    
    // good
    ;(() => {
      const name = "Skywalker";
      return name;
    })();

⬆ back to top

Type Casting & Coercion

Airbnb 와 동일합니다.

  • 21.1 문의 선두에서 형의 강제를 수행한다.

  • 21.2 문자열의 경우:

    //  => this.reviewScore = 9;
    
    // bad
    const totalScore = this.reviewScore + "";
    
    // good
    const totalScore = String(this.reviewScore);
  • 21.3 수치의 경우: Number 로 형변환하는 경우는 parseInt 를 이용하고, 항상 형변환을 위한 기수를 인수로 넘겨 준다. eslint: radix

    const inputValue = "4";
    
    // bad
    const val = new Number(inputValue);
    
    // bad
    const val = +inputValue;
    
    // bad
    const val = inputValue >> 0;
    
    // bad
    const val = parseInt(inputValue);
    
    // good
    const val = Number(inputValue);
    
    // good
    const val = parseInt(inputValue, 10);
  • 21.4 parseInt를 사용하는 경우 성능적인 이유로 문제가 되면, Bitshift를 사용한다. 이때에는 꼭! Bitshift를 사용한 이유를 주석으로 남긴다.

    // good
    /**
     * parseInt로 인해 느려졌음
     * Bitshift를 통한 수치로의 문자열 강제 형변환으로 성능을 개선시킴.
     */
    const val = inputValue >> 0;
  • 21.5 주의: Bitshift를 사용하는 경우의 주의사항. 수치는 64비트 값으로 표현되어 있으나 bitshift 연산한 경우는 항상 32비트 integer 로 넘겨진다.

    2147483647 >> 0 //=> 2147483647
    2147483648 >> 0 //=> -2147483648
    2147483649 >> 0 //=> -2147483647
  • 21.6 Boolean의 경우:

    const age = 0;
    
    // bad
    const hasAge = new Boolean(age);
    
    // good
    const hasAge = Boolean(age);
    
    // good
    const hasAge = !!age;

⬆ back to top

Naming Conventions

22.2, 22.4 ~ 5, 22.10 ~ 15 항목을 제외하고는 Airbnb 와 동일합니다.

  • 22.1 1문자의 이름은 사용하지 않는다. eslint: id-length

    // bad
    function q() {
      // ...stuff...
    }
    
    // good
    function query() {
      // ..stuff..
    }
  • 22.2 네임스페이스, 오브젝트, 함수 그리고 인스턴스에는 camelCase를 사용한다. eslint: camelcase

    // bad
    naver.FOO.bar = function() {};
    const OBJEcttsssss = {};
    const this_is_my_object = {};
    function c() {}
    
    // good
    naver.foo.bar = function() {};
    const thisIsMyObject = {};
    function thisIsMyFunction() {}
  • 22.3 클래스나 constructor에는 PascalCase 를 사용한다. eslint: new-cap

    // bad
    function user(options) {
      this.name = options.name;
    }
    
    const bad = new user({
      name: "nope",
    });
    
    // good
    class User {
      constructor(options) {
        this.name = options.name;
      }
    }
    
    const good = new User({
      name: "yup",
    });
  • 22.4 함수명이나 속성명의 앞에 _가 있는 경우는 private을 의미한다. 외부에서 접근할 수 있는 경우, 사용하면 안되는 메서드명 또는 속성명은 _을 사용한다. 외부에서 접근할 수 없다면, 메서드명 이나 속성명에 _을 사용하지 않는다. eslint: no-underscore-dangle

    // bad - 외부에서 접근할 수 있는 경우, 사용하면 안되는 메서드명 또는 속성명은 `_`을 사용한다.
    class User({
       constructor() {
          privateState: true
       }
       privateMethod() {
       }
       _publicMethod() {
       }
    }
    
    // good - 외부에서 접근할 수 있는 경우, 사용하면 안되는 메서드명 또는 속성명은 `_`을 사용한다.
    class User({
       constructor() {
          _privateState: true
       }
       _privateMethod() {
       }
       publicMethod() {
       }
    }
    
    // bad -  외부에서 접근할 수 없다면, 메서드명 이나 속성명에 `_`을 사용하지 않는다.
    (function(){
       var _privateState = true;
       function _privateMethod() {
       }
       function publicMethod() {
          _privateMethod();
       }
    })();
    
    // good -  외부에서 접근할 수 없다면, 메서드명 이나 속성명에 `_`을 사용하지 않는다.
    (function() {
       var privateState = true;
       function privateMethod() {
       }
       function publicMethod() {
           privateMethod();
       }
    })();
  • 22.5 가능한 this를 캐싱하지 않는다. arrow functions 또는 Function#bind 를 사용한다. jQuery를 사용하는 경우라면, $.proxy 를 사용한다. 만약, this의 참조를 저장하는 경우라면 self 를 사용한다.

    // 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);
      };
    }
  • 22.6 파일을 1개의 클래스로 export 하는 경우, 파일명은 클래스명과 완전히 일치시킨다.

    // file contents
    class CheckBox {
      // ...
    }
    export default CheckBox;
    
    // in some other file
    // bad
    import CheckBox from "./checkBox";
    
    // bad
    import CheckBox from "./check_box";
    
    // good
    import CheckBox from "./CheckBox";
  • 22.7 Default export가 함수일 경우, camelCase를 이용한다. 파일명은 함수명과 동일해야 한다.

    function makeStyleGuide() {
    }
    
    export default makeStyleGuide;
  • 22.8 Singleton / function library / 빈 오브젝트를 export 하는 경우에는 PascalCase를 사용한다.

    const AirbnbStyleGuide = {
      es6: {
      }
    };
    
    export default AirbnbStyleGuide;
  • 22.9 약어 및 이니셜은 항상 모두 대문자이거나 모두 소문자이어야 한다.

    // bad
    import SmsContainer from "./containers/SmsContainer";
    
    // bad
    const HttpRequests = [
      // ...
    ];
    
    // good
    import SMSContainer from "./containers/SMSContainer";
    
    // good
    const HTTPRequests = [
      // ...
    ];
    
    // best
    import TextMessageContainer from "./containers/TextMessageContainer";
    
    // best
    const Requests = [
      // ...
    ];
  • 22.10 소스의 변수명, 클래스명 등에는 영문 이외의 언어를 사용하지 않는다.

  • 22.11 한글 발음을 그대로 사용하지 않는다.

    // ''무형자산''이라는 의미의 변수를 선언한 예.
    // bad
    const moohyungJasan;
    
    // good
    const intangibleAssets;
  • 22.12 클래스, 메서드 등의 이름에는 특수 문자를 사용하지 않는다. jQuery 변수의 경우 $을 사용하는 것은 예외사항으로 한다.

    // bad
    funtion $some() {
    
    }
  • 22.13 클래스명과 변수명은 명사 사용을 준수한다.

  • 22.14 메서드명은 동사 사용을 준수한다.

  • 22.15 상수명은 대문자를 사용하고, 단어와 단어사이는 _로 연결한다.

    // bad
    const firefox = 1;
    const is_left = true;
    
    // good
    const FIREFOX = 1;
    const IS_LEFT = true;

⬆ back to top

Accessors

Airbnb 와 동일합니다.

  • 23.1 프로퍼티를 위한 접근자 (Accessor) 함수는 필수가 아니다.

  • 23.2 접근자 함수가 필요한 경우, getVal() 이나 setVal('hello') 로 한다.

    // bad
    dragon.age();
    
    // good
    dragon.getAge();
    
    // bad
    dragon.age(25);
    
    // good
    dragon.setAge(25);
  • 23.3 프로퍼티가 boolean 인 경우, isVal() 이나 hasVal() 로 한다.

    // bad
    if (!dragon.age()) {
      return false;
    }
    
    // good
    if (!dragon.hasAge()) {
      return false;
    }
  • 23.4 일관된 경우, get()set() 으로 함수를 작성해도 좋다.

    class Jedi {
      constructor(options = {}) {
        const lightsaber = options.lightsaber || "blue";
        this.set('lightsaber', lightsaber);
      }
    
      set(key, val) {
        this[key] = val;
      }
    
      get(key) {
        return this[key];
      }
    }

⬆ back to top

Events

Airbnb 와 다르게 별도의 가이드를 제공하지 않습니다.

jQuery

25.3 ~ 4 항목을 제외하고는 Airbnb 와 동일합니다.

  • 25.1 jQuery오브젝트의 변수는 선두에 $ 를 부여한다.

    // bad
    const sidebar = $(".sidebar");
    
    // good
    const $sidebar = $(".sidebar");
    
    // good
    const $sidebarBtn = $(".sidebar-btn");
  • 25.2 jQuery의 검색결과를 캐시하여 사용한다.

    // bad
    function setSidebar() {
      $('.sidebar').hide();
    
      // ...stuff...
    
      $(".sidebar").css({
        "background-color": "pink"
      });
    }
    
    // good
    function setSidebar() {
      const $sidebar = $(".sidebar");
      $sidebar.hide();
    
      // ...stuff...
    
      $sidebar.css({
        "background-color": "pink"
      });
    }
  • 25.3 Airbnb 와 다르게 DOM 검색에 대해서는 별도로 가이드 하지 않는다.

  • 25.4 Airbnb 와 다르게 DOM 검색에 대해서는 별도로 가이드 하지 않는다.

⬆ back to top

Resources

⬆ back to top