[JS] 프로토타입 체인 이해하기

초코침·2023년 3월 17일
1

JavaScript

목록 보기
17/26
post-custom-banner

프로토타입 체인 읽기 전! 프로토타입 이해하기

자바스크립트의 상속은 프로토타입을 구현한다고 했다.

누구로부터 무엇을 상속받았는지 확인하려면 나의 부모(의 부모의 부모 ….)를 계속해서 찾아나갈 수 있어야 하는데 부모 즉, 프로토타입을 찾아나가는 방법은 어떻게 구현되어 있을까?

프로토타입 체인

식별자를 스코프 체인에서 찾는 것처럼, 자바스크립트 엔진은 프로토타입 체인에서 프로퍼티와 메서드를 검색한다.

즉, 프로토타입 체인상속프로퍼티 검색의 메커니즘이다.


다음과 같이 Animal 생성자 함수가 있다.

function Animal(species, sound) {
  this.species = species;
  this.sound = sound;

  Animal.prototype.getAnimalSound = function () {
    return this.sound;
  };
}

Animal 생성자 함수로 객체를 생성하면, 그 객체는 speciessound를 자신의 프로퍼티로 갖게 된다.

const dog = new Animal('dog', 'woof');


이때 doggetAnimalSound를 소유하고 있진 않지만 호출할 수 있다. 그 이유는 Animal.prototype을 상속받았기 때문이다.


이렇게 자바스크립트는 객체의 프로퍼티나 메서드에 접근하려할 때 해당 객체(dog)에 접근하려는 프로퍼티(getAnimalSound)가 없다면 [[Prototype]] 내부 슬롯의 참조를 따라 자신의 부모 역할을 하는 프로토타입(Animal.prototype)의 프로퍼티를 순차적으로 검색한다. 이를 프로토타입 체인이라 한다.


이때 doghasOwnProperty 메서드를 소유하지 않지만 호출할 수 있는 이유도 동일한 이유다.


dog의 프로토타입 체인을 그림으로 표현하면 다음과 같다.

위 그림을 바탕으로, 자바스크립트 엔진이 hasOwnProperty 메서드를 찾는 과정은 다음과 같다.

  1. dog가 hasOwnProperty 메서드를 가지고 있는지 찾는다.
  2. 가지고 있지 않기 때문에 dog의 프로토타입 즉, Animal.prototype이 메서드를 가지고 있는지 찾는다.
  3. 가지고 있지 않기 때문에 dog의 프로토타입의 프로토타입 즉, Object.prototype이 메서드를 가지고 있는지 찾는다.
  4. Object.prototype이 hasOwnProperty를 가지고 있기 때문에 dog는 해당 메서드를 호출할 수 있다.
    → 자식 객체는 부모 객체의 프로퍼티를 상속받았기 때문에 자신의 것처럼 사용할 수 있다.

결론적으로, 자바스크립트의 상속의 메커니즘은 프로토타입 체인이다.

프로토타입 체인의 종점

프로토타입 체인의 최상위에 위치하는 객체는 언제나 Object.prototype이다. 따라서 모든 객체는 Object.prototype을 상속받는다.

Object.prototype은 프로토타입 체인의 종점이다.


그럼 이 최상위 객체의 프로토타입은 무엇일까?

__proto__접근자로 Object.prototype의 프로토타입(부모 객체)을 조회해봤더니 null이 나왔다.

Object.prototype의 내부 슬롯 [[Prototype]]은 null이다.

메서드를 당연하게 쓸 수 있었던 이유

자바스크립트의 배열은 객체라는 것을 알고 있다. 객체이기 때문에 배열에도 프로퍼티와 메서드를 정의해줄 수 있다.

우리는 배열을 선언할 때 push, pop, map, filter, reduce 등의 메서드를 함께 선언해주지 않았지만 메서드를 호출해 사용할 수 있었다. 그 이유는 바로 우리가 아무렇지 않게 선언했던 배열은 Array.prototype을 프로토타입(부모 객체)로 갖기 때문이다.

mdn 문서에서 메서드를 검색하면 항상 붙어있던 Array.prototype의 정체가 바로 배열 객체가 상속받을 프로토타입이었던 것!

[참고] 정적 프로퍼티/메서드

mdn 문서를 보면 모든 프로퍼티와 메서드가 prototype으로 표기되어 있는 것은 아니다.

이렇게 Array.prototype에 정의되어 있지 않고 Array 자신만 소유하고 있는 프로퍼티/메서드정적 프로퍼티/메서드라 한다. 정적 프로퍼티/메서드생성자 함수로 인스턴스를 생성하지 않아도 참조/호출할 수 있다.

생성자 함수가 생성한 인스턴스는 자신의 프로토타입 체인에 속한 객체의 프로퍼티에 접근할 수 있었으나, 정적 프로퍼티는 인스턴스의 프로토타입 체인에 속한 객체의 프로퍼티가 아니므로 인스턴스로 정적 프로퍼티를 참조하거나 호출할 수 없다.

따라서 해당 프로퍼티를 소유하고 있는 대상(Array, Object 등)만 정적 프로퍼티를 참조하거나 호출할 수 있다.

profile
블로그 이사중 🚚 (https://sungjihyun.vercel.app)
post-custom-banner

0개의 댓글