[JS] 7.2. 생성자를 통한 상속

작성:    

업데이트:

카테고리:

태그: , ,

참고 자료

boostcourse 생활코딩: 자바스크립트의 시작


prototype 상속

  • 현재는 class로 상속을 하면 된다.
  • 하지만 class 등장 전의 prototype으로 상속하는 방법에 대해 알아보겠다.


call 사용

function Person(name, first, second) {
  this.name = name;
  this.first = first;
  this.second = second;
}

Person.prototype.sum = function () {
  return this.first + this.second;
};

function PersonPlus(name, first, second, third) {
  Person.call(this, name, first, second); // ⭐중요!! 부모 함수의 인자 상속
  this.third = third;
}

// Person의 프로토타입 객체의 sum()을 사용하게 하기 위해
// PersonPlus의 프로토타입 객체 내의 __proto__ 프로퍼티를
// Person의 프로토타입 객체로 설정
PersonPlus.prototype.__proto__ = Person.prototype;
PersonPlus.prototype.avg = function () {
  return (this.first + this.second + this.third) / 3;
};

var kim = new PersonPlus("kim", 10, 20, 30);
console.log("kim.sum()", kim.sum());
console.log("kim.avg()", kim.avg());

원래 함수의 this의 범위가 Person에 한정되어 있었는데, 이를 PersonPlus로 가져오기 위해서 call을 사용하고, 첫 인자로 this를 두어 PersonPlus를 this의 범위로 재지정하였다.

위에서 다음의 코드를 통해 PersonPlus 함수와 프로토타입 객체에는 없는 sum() 함수를 인스턴스가 사용할 수 있도록 한다.

PersonPlus.prototype.__proto__ = Person.prototype;


Object.create 사용

PersonPlus의 프로토타입 객체의 __proto__를 Person 함수의 프로토타입 객체로 지정하는 또다른 방법이다.

// Person 함수의 프로토타입 객체를 __proto__로 연결하는 새로운 객체 생성
// 그 새로운 객체를 PersonPlus의 prototype 객체로 지정

PersonPlus.prototype = Object.create(Person.prototype);

Object.create를 굳이 사용하는 이유는 __proto__는 표준이 아니기 때문이다.


constructor

  • 어떠한 객체나 인스턴스의 .constructor 프로퍼티는 그 객체의 생성 함수 또는 부모 객체를 알 수 있게 하는 지표이다.
d = new Date();
d2 = new d.constructor();

// d2 = new Date()와 같다.

constructor()를 이용해 어떠한 객체나 인스턴스의 constructor를 모르더라도 새로 객체를 만들어낼 수 있다.


constructor 재지정

PersonPlus.prototype = Object.create(Person.prototype);
console.log("kim.constructor", kim.constructor);

// kim.constructor [Function: Person]
  • kim은 분명 PersonPlus의 인스턴스인데, constructor를 console.log로 찍어보면 Person 함수라고 표시된다.
  • 이는 PersonPlus의 prototype을 Person.prototype으로 하여 replace했기 때문이다.


  • 이를 고치는 방법은 다음과 같다.
// PersonPlus의 프로토타입 객체의 생성자를 PersonPlus로 재지정
PersonPlus.prototype.constructor = PersonPlus;


다시 __proto__

  • 위와 같은 방법은 기존에 PersonPlus.prototype에 어떠한 프로퍼티나 메서드가 있었어도 새로 재정의되는 파괴적인 방식이기 때문에 사용하지 못할 수 있다.

  • 이를 해결하는 방법이 위에서 언급한 __proto__이다.

PersonPlus.prototype.__proto__ = Person.prototype;
  • Object.create의 경우 PersonPlus의 프로토타입에 avg 메서드를 정의한 이후 replace해버리면 avg 메서드가 사라진다. 순서가 바뀌면 오류가 생길 수 있다.

  • __proto__의 경우 soft한 방식으로 참조하는 주소만 바꾸는 것이기 때문에 위험하지 않다. 다만 __proto__는 권장되는 방식이 아니기 때문에 상황에 따라 잘 선택하면 되겠다.

  • 그냥 class 써라. 가장 깔끔하고 직관적이다.


Quiz 오답노트

image

문제를 잘못 읽어서 틀렸지만, 1번과 4번은 문법적으로 옳지 않은 방식이고, 내가 찍은 2번은 단순히 복제만 하는 방식이다. 3번이 superObj를 모체로 하여 상속해주는 subObj 객체를 만드는 방법이었다.


image

제일 헷갈리는 문제였다. 배우기로는 Object.create(Person.prototype)이 맞는데 prototype이 자꾸 replace돼서 밀린다는 식으로 말씀하셔서 정확히는 같지 않은가 하고 제외했는데, 가장 정답에 근접한 답안이었나보다.

댓글남기기