🔥 학습목표
- 프로토타입이 무엇인지 설명할 수 있다.
- 프로토타입과 클래스의 관계에 대해 설명할 수 있다.
- 자바스크립트 DeepDive 19장을 학습한다.
자바스크립트는 객체 지향 프로그래밍 언어이며
(원시 타입 제외) 이루고 있는 거의 모든 것이 객체라고 했다.
[S2U2] 클래스와 인스턴스 에서 간단하게 지나간 부분이 있다.
자바스크립트는 프로토타입을 기반으로 한 객체지향 프로그램이다.
라는 부분이다.
저놈의 프로토타입이 뭐길래 객체 지향 프로그래밍을 돕는다고 할까?
간단하게 말하자면, 프로토타입 == 상속 이다.
자바스크립트는 프로토타입을 기반으로 상속을 구현 => 불필요한 중복을 제거한다.
기존의 코드를 적극적으로 재사용하고 개발 비용을 줄인다.
프로토타입 기반으로 상속을 구현하지 않고
인스턴스 객체를 생성하는 경우를 살펴보자.
Circle 생성자 함수는 두 개의 인스턴스를 만든다.
한 개는 반지름이 1이고, 다른 하나는 2인 원이다. 이 두 개의 원은 반지름을 제외하고 면적을 구하는 기능은 똑같다.
function Circle(radius) {
this.radius = radius;
this.getArea = function() {
return Math.PI * this.radius ** 2;
};
}
const circle1 = new Circle(1);
const circle2 = new Circle(2);
console.log(circle1.getArea === circle2.getArea); // false
그런데 Circle 생성자 함수는 인스턴스를 생성할 때마다 getArea 메서드를 중복 생성하고
모든 인스턴스는 같은 메서드를 중복 소유하게 된다.
10개의 인스턴스를 생성하면 동일한 메서드가 10개 생성되는 것이다.
이는 메모리 낭비를 불러온다.
동일한 내용의 메서드는 단 하나만 생성해서 모든 인스턴스가 공유하는 게 효율적이다.
Circle 생성자 함수가 생성한 모든 인스턴스는 Circle 생성자 함수의 프로토타입,
즉 상위(부모) 객체 역할을 하는 Circle prototype의 모든 프로퍼티와 메서드를 상속 받는다.
getArea 메서드는 단 하나만 생성되어 Circle.prototype의 메서드로 할당되어 있다.
Circle 생성자 함수가 생성하는 모든 인스턴스는 getArea 메서드를 상속 받아 사용한다.
자신의 상태를 나타내는 radius 프로퍼티만 개별적으로 소유하는 것이다.
function Circle(radius) {
this.radius = radius;
}
Circle.prototype.getArea = function() {
return Math.PI * this.radius ** 2;
};
const circle1 = new Circle(1);
const circle2 = new Circle(2);
console.log(circle1.getArea === circle2.getArea); // true
그림으로 나타내면 아래와 같다.
책에 나와있는 그림이지만 내가 직접 다시 그리면서 기억에 남기고 싶어 그려봤다.
프로토타입이란?
어떤 객체의 상위(부모) 객체의 역할을 하는 객체이다.
모든 객체는 [[Prototype]]
이라는 내부 슬롯을 가지며, 내부 슬롯의 값은 프로토타입의 참조다.
객체가 생성될 때 프로토타입이 결정 되고 [[Prototype]]
에 저장 된다.
객체 리터럴로 생성된 객체의 프로토 타입은 Object.prototype
이다.
생성자 함수로 생성된 객체의 프로토타입은 생성자 함수의 property
프로퍼티에 바인딩 되어있는 객체다.
__proto__
접근자 프로퍼티자신의 프로토타입, 즉 [[Prototype]] 내부 슬롯에 간접적으로 접근한다.
__proto__
는 객체 자신의 것이 아니다?__proto__
접근자 프로퍼티는 Object.prototype
의 프로퍼티다.Object.prototype.__prototype__
을 사용한다.Object.prototype
프로토타입 체인의 최상위 객체이다. 이 객체의 프로퍼티와 메서드는 모든 객체에 상속 된다.
hasOwnProperty( );
객체 자신이 직접 소유하는 프로퍼티인지 체크하는 메서드이다.
__proto__
접근 이유상호 참조에 의해 프로토타입 체인이 생성되는 것을 방지하기 위해 사용된다.
└▷ 부모가 자식을 프로토타입으로, 자식이 부모를 프로토타입으로 가지는 것.
__proto__
접근자 프로퍼티를 코드 내에서 직접 사용하는 것은 권장하지 않는다.
직접 상속을 통해 Object.prototype
을 상속받지 않는 객체를 생성할 수도 있기 때문이다. 그럴 경우 __proto__
접근자 프로퍼티는 사용할 수 없게 된다.
대신 Object.getPrototypeOf(obj) 를 사용하자.
생성자 함수가 생성할 객체(인스턴스)의 프로토타입을 가리킨다.
prototype 프로퍼티로, 자신을 참조하고 있는 생성자 함수를 가리킨다.
위 그림을 참고한다.
프로토타입 체인에 대해서는 '모던자바스크립트DeepDive' 에 예시와 그림이 아주 간결하게 잘 정리되어 있어... 따로 블로깅 하는 데 시간을 투자할 필요가 없을 정도다.
프로토타입 체인이 궁금한 미래의 나는 19.7장(285p)를 참고하도록.