June

자바스크립트 상속 모델

몇일 전, 페이스북에 아래와 같은 질문이 올라왔었습니다.


javascript에서 상속구조를 만들 때

function Person(name) {
  this.name = name;
}
function Student(name, school) {
  Person.call(this, name);
  this.school = school;
}

Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;

var student1 = new Student("lee", "a");
console.log(student1.name) //lee

이런 식으로 만들고 있는데,
Student.prototype = Object.create(Person.prototype);
이 부분에서 이 것과
Student.prototype = new Person();
을 하는 것의 큰 차이점을 잘 모르겠습니다 ㅠ_ㅠ

위 질문에 맞는 대답은 해드렸지만 최근에 프로토타입에 대해 소홀한 부분이 있어서 자바스크립트에서의 상속에 대해 한번 정리를 해보려합니다.


자바스크립트가 사용하는 프로토타입 모델에서의 상속은 아래와 같습니다.

function Foo() {
  this.value = 1;
}

Foo.prototype.method: function() {}

function Bar() {}

// Foo의 인스턴스를 만들어 Bar의 prototype에 할당
Bar.prototype = new Foo();
// Bar의 prototype의 생성자는 자기 자신.
Bar.prototype.constructor = Bar;

var barz = new Bar() // bar 인스턴스를 만든다.

결과

barz의 생성자 Bar의 prototype은 Foo입니다. Foo의 constructor는 Bar를 가리키며, Foo의 prototype은 Object를 가리킵니다. 하지만 Object의 프로토타입은 다시 Foo를 가리키죠.

    1. barz의 constructor -> Bar
    1. Bar의 prototype -> Foo, Foo의 constructor -> Bar
      1. 클래스의 상속 개념을 가지는 Bar, Foo와 같은 함수들은 prototype, constructor로 순환구조를 가지게 됩니다.
    1. Foo의 prototype -> Object
      1. 순환구조 최상위인 Object에 도달하면 끝이나게 됩니다.

result

예외 케이스

만약 Bar의 프로토타입 생성자 (Bar.prototype.constructor)를 정해주지 않으면, 상속받은 함수(new Foo())를 가리키게 됩니다.

exception

하지만

비슷하지만 최근엔 다른 방식을 지향하게 되었습니다. 거의 똑같지만! Bar.prototype = new Foo(); 대신 Bar.prototype = Object.create(Foo.prototype); 를 하는것이죠. 물론 prototype.constructor도 이전과 마찬가지로 동일하게 정의해줘야 합니다. new Foo()를 해도 상관은 없지만, new 연산을 사용하면 아래와 같은 이슈(??)가 생깁니다.

issue

Bar.prototype = new Foo();를 하면 필요없는 객체의 데이터까지 들어오게 됩니다. 사실 무시할 수도 있지만, 본래의 역활과 다른 무언가까지 생기는게 찝찝하긴 합니다.

또한, Object.create에도 약간의 이슈가 있는데요, IE9과 같은 마이너 브라우저에서 사용할 수 없다는 점입니다. 이 부분은 아래 코드처럼 사전 정의를 통해 해결할 수 있습니다.

Object.create = function(o) {
  function F() {}
  F.prototype = o;
  return new F();
};

참고 : [속깊은 자바스크립트 강좌] 상속, new와 object.create의 차이


읽어주셔서 감사합니다.