[TIL] Prototype Chain

Ha Young Do·2021년 4월 18일

Javascript는 프로토타입 기반 언어라고 불린다. 객체를 처음 만들 때에 프로토타입 객체를 청사진으로 두고 그것을 기반으로 메소드와 속성을 상속받는 것이다. 하나의 프로토타입 객체는 다른 프로토타입 객체를 부모로 두고 그 부모 프로토타입 객체로부터 속성과 메소드를 상속받을 수 있다. 이렇게 여러 프로토타입이 상속관계로 연결되는 현상을 prototype chain이라고 부른다.

__proto__, constructor, prototype

  • __proto__: 객체의 이 속성을 통해 현 객체에 상속을 시켜 주는 프로토타입 객체에 접근할 수 있다. 프로토타입 객체를 가져오는 getter 함수의 일종으로 볼 수 있다. 프로토타입 객체를 설정하는 setter 함수로도 쓰일 수 있으나, 현재는 사장된 (deprecated) 용법으로 사용을 추천하지 않는다.
  • constructor: 모든 프로토타입 객체가 가지고 있는 속성으로, 생성자 함수를 참조한다.
  • prototype: 모든 생성자 함수가 가지고 있는 속성으로, 프로토타입 객체를 참조한다. 이 속성을 사용해서 프로토타입 객체를 assign 해 줄 수도 있다.
  • instantation: 생성자 함수를 호출하여 한 객체의 새로운 경우 (instance) 를 만드는 행위를 말하며 모든 instance는 프로토타입 객체의 속성을 공유한다.

pseudosubclassing before ES6

function Human (name) {
  this.name = name;
}

Human.prototype.sleep = function () {
  console.log('Zzz');
}

Human.prototype.breathe = function () {
  console.log('Inhale, exhale, inhale, exhale...');
}
function Student (name){
	Human.call(this, name); // this의 context를 Human 단계까지 올려주는 메소드
}

Student.prototype = Object.create(Human.prototype);
Student.prototype.constructor = Student;
Student.prototype.learn = function () {
    console.log('Coding...');
}

Object.create() 메소드를 이용하여 Human 프로토타입 객체를 복사한 Student 프로토타입 객체를 만든다.

subclassing in ES6

ES6에서는 이전의 복잡한 문법을 보완하여 class 키워드, super 키워드를 사용하여 간결하게 subclassing이 가능하다.

class Human {
  constructor (name) {
    this.name = name;
  }
  
  sleep () {
    console.log('Zzz');
  }
  
  breathe () {
    console.log('Inhale, exhale, inhale, exhale...');
  }
}

let me = new Human('Ha Young');
me.sleep(); // 'Zzz'
me.breathe(); // 'Inhale, exhale, inhale, exhale...'

function 대신 class 키워드를 사용하여 새로운 객체 클래스를 정의한다.

class Student extends Human {
  constructor (name) {
  	super (name)
  }
  
  breathe () {
    console.log('I live and breathe JavaScript');
  }
  
  learn () {
    console.log('Coding...');
  }
}

let sparklingWater = new Student('Ha Young')
sparklingWater.sleep(); // 'Zzz'
sparklingWater.breathe(); // 'I live and breathe JavaScript'
sparklingWater.learn(); // 'Coding...'

extends 키워드를 통해 Student가 Humand을 부모로 한 자식 클래스임을 명시해 주고, super 키워드를 이용하여 부모 클래스의 속성을 받아 온다. (부모 클래스와 자식 클래스가 같은 argument를 사용하는 경우 super문은 생략 가능하다.) 부모 클래스에서 상속한 메소드는 자식 클래스 안에서 덮어쓸 수 있다.

Student.prototype.breathe () {
  Human.prototype.breathe.call(this);
  console.log('I live and breathe JavaScript');
}

만약 덮어쓰는 것이 아니라 기본 동작을 확장하는 식으로 수정하고 싶으면 부모 클래스의 메소드를 call이나 apply를 통해 호출한 후 내용을 덧붙이는 식으로 진행한다.

prototype chain in action


steve라는 Human의 새로운 instance를 만들어 주었을 때, steve의 __proto__ 속성을 통해 Human의 프로토타입 객체에 접근할 수 있다.


동일하게 Human의 프로토타입 객체의 __proto__ 속성을 통해 Object의 프로토타입 객체에 접근할 수 있다.

me라는 Student의 새로운 instance를 만들어 주었을 때, me의 __proto__ 속성을 통해 Human이 아닌 Student의 프로토타입 객체에 접근할 수 있다.

me는 Student의 instance이고, (Student는 Human으로부터 상속받기에) 동시에 Human의 instance이지만, steve는 Human의 instance이고, Student의 instance는 아니다.

profile
Codestates Software Engineering Full IM 28th

0개의 댓글