프론트엔드/JavaScript

[JavaScript] Prototype

1. Prototype (프로토타입)

JavaScript는 프로토타입 기반 객체지향 프로그래밍 언어이다.

 

JavaScript의 모든 객체상속되는 정보가 담긴 프로토타입(prototype) 객체를 가지고 있다.

이를 통해 모든 객체는 자신의 프로토타입으로부터 프로퍼티와 메소드들을 상속받을 수 있다.

덕분에 JavaScript는 클래스 없이 프로토타입만으로 객체를 생성할 수 있다.

 

(ES6에서 클래스 문법 추가)


2. [[Prototype]] vs prototype 프로퍼티

모든 객체는 자신의 프로토타입을 가리키는 [[Prototype]] 이라는 내부 슬롯(internal slot)을 갖는다.

(내부 슬롯은 은닉 속성 정도로 해석되며, 상속을 위해 사용된다.)

 

함수도 객체이므로 [[Prototype]] 을 갖는다.

그런데 함수는 일반 객체와 달리 prototype 프로퍼티도 갖는다.

[[Prototype]]와 prototype 프로퍼티 모두 프로토타입 객체를 가리지만 다음과 같은 차이가 있다.

 

  • [[Prototype]]
    • 함수를 포함한 모든 객체가 가지고 있는 내부 슬롯
      • 객체부모 역할을 하는 프로토타입 객체를 가리킴
      • 함수 객체Function.prototype를 가리킴
  • prototype 프로퍼티
    • 함수 객체만 가지고 있는 프로퍼티
    • 함수 객체가 생성자로 사용될 때, 이 함수를 통해 생성될 객체의 부모 객체(프로토타입 객체)를 가리킴

3. constructor 프로퍼티

프로토타입 객체는 constructor 프로퍼티를 가지며 이는 자신을 생성한 객체를 가리킨다.

생성자 함수에 의해 생성된 객체라면 해당 생성자 함수를 가리킨다.

 

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

var foo = new Person('Lee');

// Person() 생성자 함수에 의해 생성된 객체를 생성한 객체는 Person() 생성자 함수이다.
console.log(Person.prototype.constructor === Person);

// foo 객체를 생성한 객체는 Person() 생성자 함수이다.
console.log(foo.constructor === Person);

// Person() 생성자 함수를 생성한 객체는 Function() 생성자 함수이다.
console.log(Person.constructor === Function);

4. Prototype chain

만약 특정 객체의 프로퍼티나 메소드에 접근할 때 해당 프로퍼티 또는 메소드가 없을 수 있다.

이렇게 되면 [[Prototype]]이 가리키는 링크를 따라 상위 프로토타입 객체를 차례대로 탐색한다.

이를 프로토타입 체인(Prototype chain)이라 부른다.

 

또한 Object.prototype 객체는 이러한 프로토타입 체인에서도 가장 상위에 존재하는 프로토타입이다.

그래서 JavaScript의 모든 객체는 Object.prototype 객체를 프로토타입으로 상속받는다.