Little Jay

[JS] Prototype 상속은 어떻게 이루어지는가 본문

FrontEnd/Front End Interview Handbook

[JS] Prototype 상속은 어떻게 이루어지는가

Jay, Lee 2023. 1. 26. 22:55

 자바스크립트 관련 단골 질문 중 하나입니다. 자바스크립트에서 모든 객체는 __proto__ 속성을 가지고 있습니다. 단, 어떤 객체가 Object.create(null)을 사용해서 생성이 되었다면, __proto__는 만들어지지 않습니다. 이 __proto__ property는 다른 객체에 대한 참조이며, 이를 객체의 "prototype"이라고 합니다. 만약 객체의 property에 접근하고, 해당 객체에서 property가 발견되지 않았을 때 자바스크립트 엔진(Javascript Engine)은 해당 객체의 __proto__를 살펴보기 시작합니다. 이때 __proto__만 참조하는 것이 아니라, __proto____proto__를 계속해서 찾아보는데, 이 __proto__중 하나에 property가 정의될 때 까지, 혹은 prototype의 Chain의 끝에 도달할 때까지 계속해서 __proto____proto__를 확인합니다. 이러한 자바스크립트의 prototype의 동작은 클래식한 상속을 연상시키지만, 실제로는 위임에 조금 더 가깝다고 할 수 있습니다. 

(이 부분에 대해서는 https://davidwalsh.name/javascript-objects 이 링크를 참조하면 되겠습니다. 저도 번역만 한 것이기 때문에 공부를 조금 더 하고 수정하겠습니다. )

 

코드를 한번 보시죠.

function Parent() {
  this.name = 'Parent';
}

Parent.prototype.greet = function () {
  console.log('Hello from ' + this.name);
};

const child = Object.create(Parent.prototype);

child.cry = function () {
  console.log('waaaaaahhhh!');
};

child.cry();
// waaaaaahhhh!

child.greet();
// hello from Parent

child.constructor;
// ƒ Parent() {
//   this.name = 'Parent';
// }

child.constructor.name;
// 'Parent'

.greet은 child에 define되지 않았습니다. 따라서 Javascript Engine은 해당 property가 하위 항목에 정의되어 있지 않으므로 프로토타입 체인을 위로 타고 올라가면서 상위 항목에서 상속된 .greet를 찾습니다. 그러나 출력결과는 hello from parent가 나오게 됩니다. 따라서 제대로 프로토타입 메서드가 상속되려면 다음 방법 중 하나로 Object.create를 호출해야 합니다.

  • Object.create(Parent.prototype)
  • Object.create(new Parent(null));
  • Object.create(objLiteral);

 그리고 주의할 점은 현재 child.constructor가 부모를 가리키고 있다는 것 역시 염두해 두어야합니다. 따라서 정확한 결과를 만들기 위해서는 다음과 같이 코드를 수정할 수 있겠습니다. 이 방법이 unique한 방법은 아닙니다. 

function Parent() {
  this.name = 'Parent';
}

Parent.prototype.greet = function () {
  console.log('Hello from ' + this.name);
};

function Child() {
  Parent.call(this);
  this.name = 'Child';
}

Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

const child = new Child();

child.greet();
// hello from Child

child.constructor.name;
// 'Child'

Reference

https://www.frontendinterviewhandbook.com/javascript-questions#explain-how-prototypal-inheritance-works

 

Comments