JavaScript - 프로토타입과 클래스의 관계

Kim-DaHam·2023년 3월 15일
0

JavaScript

목록 보기
11/18
post-thumbnail

🔥 학습목표

  • 프로토타입이 무엇인지 설명할 수 있다.
  • 프로토타입과 클래스의 관계에 대해 설명할 수 있다.
  • 자바스크립트 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 프로퍼티

생성자 함수가 생성할 객체(인스턴스)의 프로토타입을 가리킨다.

  • 프로토타입과 생성자 함수는 단독으로 존재할 수 없고 언제나 쌍으로 존재한다.
  • 프로토타입은 함수가 생성되는 시점에 더불어 생성 된다.

🟣 constructor 프로퍼티

prototype 프로퍼티로, 자신을 참조하고 있는 생성자 함수를 가리킨다.

위 그림을 참고한다.


🟩 프로토타입 체인

프로토타입 체인에 대해서는 '모던자바스크립트DeepDive' 에 예시와 그림이 아주 간결하게 잘 정리되어 있어... 따로 블로깅 하는 데 시간을 투자할 필요가 없을 정도다.

프로토타입 체인이 궁금한 미래의 나는 19.7장(285p)를 참고하도록.



profile
다 하자

0개의 댓글