1 minute read

모던 자바스크립트 Deep Dive 19장을 정리한 글입니다.

프로토타입

자바스크립트는 클래스와 상속, 캡슐화를 위한 키워드가 없지만 프로토타입을 기반으로한 객체지향 프로그래밍 언어이다. (명령형, 함수형 프로그래밍 또한 지원하는 멀티 패러다임 언어)

상속(inheritance)는 어떤 객체의 프로퍼티 또는 메서드를 다른 객체가 상속받아 그대로 사용할 수 있는 것을 말한다. 자바스크립트는 프로토타입으로 상속을 구현하며 이를 통해 불필요한 중복을 제거할 수 있다.

function Circle(radius) {
  this.radius = radius;
  this.getArea = function () {
    return 2 * Math.PI ** this.radius;
  };
}
console.log(new Circle(1).getArea === new Circle(1).getArea); // false

function Circle2(radius) {
  this.radius = radius;
}
// 프로토타입을 이용한 코드 중복 제거
Circle2.prototype.getArea = function () {
  return Math.PI * this.radius ** 2;
};
console.log(new Circle2(1).getArea === new Circle2(1).getArea); // true

프로토타입 접근 방법

모든 객체는 [[Prototype]]이라는 내부 슬롯을 가지만 null인 경우도 있다. 모든 객체는 하나의 프로토타입을 가질 수 있으며 이는 생성자 함수와 연결되어 있다. 해당 객체가 어떤 생성자 함수에 의해 생성되었는가에 따라 [[Prototype]]에 저장되는 프로토타입이 결정된다.

__proto__

Object 생성자 함수(Object.prototype)의 상속을 통해 사용할 수 있는 접근자 프로퍼티이다. 모든 객체는 대부분 생성자 함수에 의해 생성되기 때문에 __proto__를 통해 자신의 생성자 함수의 prototype 프로퍼티를 확인할 수 있다.

function Person(name) {
  this.name = name;
}
const me = Person("mhy");
console.log(me.__proto__ === Person.prototype); // true

생성자함수.prototype

위의 접근자 프로퍼티 __proto__와 동일한 생성자 함수의 prototype 프로퍼티를 가리키는 역할이다. 차이점은 사용 목적에 있으며 생성자 함수가 생성할 인스턴스의 프로토타입을 할당하기 위해 사용된다.

function Person(name) {
  this.name = name;
}
Person.prototype.sayHi = function () {
  console.log("Hi");
};
const me = Person("mhy");
console.log(me.sayHi()); // Hi

프로토타입 생성

모든 프로토타입은 생성자 함수가 생성되는 시점에 생성된다. 즉, 함수 정의가 평가되어 함수 객체가 생성되는 시점에 더불어 생성된다. 이후 생성자 함수에 의해 생성되는 인스턴스의 [[Prototype]] 내부 슬롯에 할당되어 상속이 구현된다.

프로토타입 체인

프로터타입 체인이란 객체의 메서드, 프로퍼티에 접근할 때 해당 객체에 없으면 [[Prototype]] 내부 슬롯의 참조를 따라 자신의 부모 역할을 하는 프로토타입의 프로퍼티를 순차적으로 검색하는 메커니즘이다.

프로토타입 체인은 상속과 프로퍼티 검색을 위한 메커니즘에 해당하고 스코프 체인은 식별자 검색을 위한 메커니즘이다. 이 둘은 서로 협력하여 식별자와 프로퍼티를 검색한다.

function Person(name) {
  this.name = name;
}
console.log(Object.getPrototypeOf(me) === Person.prototype); // true;
console.log(Object.getPrototypeOf(Person.prototype) === Object.prototype); // true;

위와 같이 프로토타입의 포로토타입은 언제나 Object.prototype이 된다. 따라서 모든 객체는 Object.prototype을 상속받을 수 있고 Object.prototype은 체인의 종점(end of prototype chain)이라 한다.