프로토타입

Hyeon·2021년 10월 10일
0

상속과 프로토타입

프로토타입은 자바스크립트에서 상속을 구현하기 위해 만들어졌다.

function Square(x) {
  this.x = x;
  this.getArea = function () {
    return this.x **2;
  };
}

const s1 = new Square(5);
const s2 = new Square(6);

console.log(s1.getArea());//25
console.log(s2.getArea());//36
console.log(s1.getArea === s2.getArea);//false

Square의 인스턴스를 생성할 때마다 getArea 메서드를 생성하고, 모든 인스턴스가 getArea 메서드를 중복해서 소유하게 된다. 이는 퍼포먼스와 메모리 측면에서 좋지 않다.

프로토타입을 통해 다음과 같이 변경할 수 있다.

function Square(x) {
  this.x = x;
}

Square.prototype.getArea = function () {
  return this.x ** 2;
};

const s1 = new Square(5);
const s2 = new Square(6);

console.log(s1.getArea()); //25
console.log(s2.getArea()); //36
console.log(s1.getArea === s2.getArea); //true

Square 생성자 함수의 프로토타입에 getArea 메서드를 추가했다.
getArea메서드는 한번만 생성되고 Square 생성자 함수의 모든 인스턴스는 getArea를 상속받아 사용할 수 있다.

생성자 함수, 프로토타입, 객체

생성자 함수, 프로토타입, 객체는 세트라고 생각하면 된다. 자바스크립트에서 거의 모든 것은 객체다. 그리고 모든 객체는 하나의 프로토타입을 갖고, 모든 프로토타입은 하나의 생성자 함수를 갖는다.

모든 객체는 [[Prototype]]이라는 내부슬롯을 가진다. 객체가 만들어 질 때 prototype이 결정되고, 슬롯에 할당된다. 내부 슬롯에 직접 접근할 수 없는대신 __proto__라는 접근자 프로퍼티를 통해 프로토타입에 접근할 수 있다. 프로토타입은 constructor 프로퍼티를 통해서 생성자 함수에 접근할 수 있다.

위 Square를 예시로 들면 다음과 같은 구조라고 할 수 있다.

Square {
	protorype : Square.prototype
}

Square.prototype {
	constructor : Square
}

s1 {
	[[Prototype]] : Square.prototype을 가리킴(직접 접근불가)
   	__proto__: Square.prototype
}

직접 출력해보면 다음과 같다.

function Square(x) {
  this.x = x;
}

Square.prototype.getArea = function () {
  return this.x ** 2;
};

const s1 = new Square(5);

console.log(s1.__proto__);//{ getArea: [Function (anonymous)] }
console.log(s1.__proto__.constructor);//[Function: Square]

s1에서 __proto__를 통해 Square.prototype에 접근한다.

Square.prototype에서 constructor를 통해 Square 생성자 함수에 접근한다.

프로토타입 체인

위에서 __proto__는 접근자 프로퍼티라고 했다. 그렇다면 __proto__는 어디서 온 것일까?

__proto__는 Object.prototype의 접근자 프로퍼티이다.

프로토타입의 프로토타입은 언제나 Object.prototype이다. 자바스크립트는 객체에 접근하려는 프로퍼티가 없다면 [[Prototype]] 슬롯의 참조를 따라 부모 역할을 하는 프로토타입의 프로퍼티를 순차적으로 검색한다. 이를 프로토타입 체인이라고 한다.

위 예시에서는 다음과 같은 과정으로 검색이 이루어진다.

  1. 만들어진 s1 객체에서 __proto__ 를 찾는다.
  2. 없다면 s1의 [[Prototype]]에 바인딩 되어있는 Square.prototype 에서 __proto__를 찾는다.
  3. 없다면 Square.prototype의 [[Prototype]]에 바인딩 되어있는 Object.prototype에서 __proto__를 찾는다.

0개의 댓글