goongoguma's blog

Using class in JS?

  • ES6에 추가된 class 관련 글들을 찾아보면 class의 사용을 권장하지 않는 글들이 많다.
  1. 자바와 C++을 사용했던 많은 개발자들이 자바스크립트로 넘어오면서 자바스크립트에서도 oop를 따라하려는 시도로 class개념이 es6에 도입됨. 그러나…

  2. 자바스크립트의 class는 생성자 함수와 프로토타입 상속의 synthetic sugar일 뿐이다.

  3. 자바스크립트의 프로토타입 객체를 수정해야 한다.

  4. 더글라스 크락포드에 따르면 es6에서 추가된 class는 개발자들을 class를 사용하는 모델에서 벗어나지 못하게 만듦으로써 es6에 있어 최악의 업데이트라고 했다. (https://vimeo.com/97419177, 20:00)

  5. class 기반인 객체지향 언어는 클래스의 상속 정보를 이용해 상속 구조 모습을 가진 새로운 객체의 틀을 뽑아내는 반면에 프로토타입을 통한 상속 구조는 존재하는 객체끼리 연결을 동적으로 표현한다. 즉 상속 받은 객체의 내용을 동적으로 추가, 삭제할 수 있다.

  6. 자바스크립트는 this는 함수가 어디서 정의되느냐가 아니라 어떻게 호출되는지에 따라 값이 달라진다.

function Person(name) {
  this.name = name;
}
Person.prototype.talk = function () {
  console.log(`${this.name} says hello`);
};

// 여기서 알아두어야 할 점은 talk 함수가 Person class의 캡슐화된 메소드가 아니라
// 객체 Person이 상속받은 함수라는것.

const Grey = new Person("Grey");
const mockDomObj = {};
mockDomObj.onClick = Grey.talk;
mockDomObj.onClick(); // this.name -> undefined!

// 예시에서 mockDomobj.onClick에서 this.name을 호출하게 되면 mockDomObj에서
// name이라는 프로퍼티를 찾는다.

mockDomObj.name = "button";
mockDomObj.onClick(); // this.name -> 'button'
  • 위의 예시처럼 자바스크립트의 class는 캡슐화가 가능한 다른 class-based 언어와 다르게 동작하며 자바스크립트를 처음 접해본 사람들을 이해하기 어렵게 만든다.
  1. 자바스크립트에서 class 보다는 객체를 반환하는 팩토리 함수를 사용해보는것도 좋다.
  const PersonFactory = (name) => ({
    talk() {
      console.log(`${name} says Hello`)
    };
  });
  • 팩토리 함수를 사용한다면 클로저를 활용하기 때문에 bind나 this를 사용하지 않아도 된다.
const Grey = PersonFactory("Grey");
const mockDomObj = {};
mockDomObj.onClick = Grey.talk;
mockDomObj.onClick(); // -> Grey says Hello
  • 팩토리 함수를 사용하니 name 프로퍼티를 private으로 만들었다.
  • 만약에 프로퍼티를 공유하고 싶다면 extends와 같은 키워드가 필요하지 않다. 대신 팩토리 함수에서 생성되는 객체를 변환하면 된다. 예를들어 Object.assign을 사용해서 PersonFactory 함수가 Mammal 프로퍼티를 공유하게 할 수도 있다.
const Mammal = {
  isVertebrae: true,
};

const PersonMammalFactory = (name) =>
  Object.assign({}, Mammal, PersonFactory(name));