JS/자바스크립트 Style Guide

8. Classes & Constructors(JS style guide)

코비코 koreanvisionarycoder 2022. 12. 27. 10:17

Classes & Constructors 클래스 사용 > 프로토타입 직접조작


Always use class. Avoid manipulating prototype directly.

  • prototype을 직접 조작하는 것보다 class를 활용한다. 
  • class 문법은 prototype의 조작보다 더 간결하며, 의미를 알기 쉽기 때문이다.
// 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;
  }
}

/* 참고: 언더바(_) 변수
코딩 컨벤션의 일종이며, 해당 함수 내부에서 사용될 변수 또는 함수임을 암시하기 위함. (java의 private과 유사)
class Injuk {
  constructor(contents = []) {
    console.log(this);
    console.log(this._injuk);
    this._injuk = [...contents];
    console.log(this._injuk);
  }
}

let injuk = new Injuk([1, 2, 3]);

실행 결과:
Injuk {} // 실행 context는 Injuk{} 클래스
undefined // this._injuk 초기화 전
[ 1, 2, 3 ] // this._injuk 초기화 후
*/

 

 

상속: extends 사용


Use extends for inheritance.

  • 상속은 extends를 사용합니다.
  •  It is a built-in way to inherit prototype functionality without breaking .instanceof
  • instanceof를 사용할 수 있으면서 함께 프로토타입 상속을 받을 수 있게 구현된 Built-in 방식이다.
// 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];
  }
}

/* inherits 검증 필요

*/

 

 

클래스 메서드 체이닝: 메서드가 this 를 return


Methods can return this to help with method chaining.

  • 메소드의 반환값으로 this 를 반환하는 것으로 메소드채이닝을 할 수 있다.
// bad
// prototype을 사용하며, return이 적절하지 않게 구현되었습니다.
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 방식을 사용하며, 메소드가 context(이 경우, Jedi{})를 반환하여 연속된 메소드 사용(메소드 체이닝)이 가능합니다.
class Jedi {
  jump() {
    this.jumping = true;
    return this;
  }

  setHeight(height) {
    this.height = height;
    return this;
  }
}

const luke = new Jedi();

luke.jump()
  .setHeight(20);

 

클래스의 커스텀 toString() 메서드


 It's okay to write a custom toString() method, just make sure it works successfully and causes no side effects.

  • 확인해야 할점 : class 별로 독자적인 toString()을 사용하는 것은 허용되나, 정상 동작 여부와 side effect 여부를 확인해주시기 바랍니다.
class Jedi {
  constructor(options = {}) {
    this.name = options.name || 'no name';
  }

  getName() {
    return this.name;
  }
  // It's Okay... just make sure it
  toString() {
    return `Jedi - ${this.getName()}`;
  }
}

 

default 생성자  eslint: no-useless-constructor


  • 빈 constructor 생성자는 생략해도 된다.
  • 빈 생성자를 가지는 클래스를 상속하는 클래스에서, 또한 빈 생성자를 가지고 있을 땐 constructor 가 불필요하다. 
// bad
class Jedi {
  constructor() {}

  getName() {
    return this.name;
  }
}

// bad
class Rey extends Jedi {
  constructor(...args) {
    super(...args);
  }
}

class Jedi {
  getName() {
    return this.name;
  }
}

class Rey extends Jedi { }

// good
class Rey extends Jedi {
  constructor(...args) {
    super(...args);
    this.name = 'Rey';
  }
}
 
 
 
 

 

중복된 클래스 멤버를 가지는 클래스 X . 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; }
}
 
 
 
 

 

클래스 메서드에서 this 를 사용하지 않을 경우 : static 메서드 사용 eslint: class-methods-use-this


// bad
class Foo {
  bar() {
    console.log('bar');
  }
}

// good - this 를 사용할 경우 -> 일반 메서드
class Foo {
  bar() {
    console.log(this.bar);
  }
}

// good - constructor 를 생략할 수 있다.
class Foo {
  constructor() {
    // ...
  }
}

// good - this 를 사용하지 않은 경우 -> static methods, 정적 메소드는 this를 사용하지 않는다고 예상할 수 있습니다
class Foo {
  static bar() {
    console.log('bar');
  }
}