Programming Language/JS & TS

[JS] Prototype과 __proto__

monkeykim 2024. 10. 17. 00:01

JavaScript를 사용하면서 한 번쯤 들어봤을 프로토타입(prototype)__proto__. 이 둘은 JavaScript의 객체지향 프로그래밍에서 매우 중요한 개념이지만, 처음 접할 때는 다소 혼란스러울 수 있다. 이번 글에서는 ES6 문법을 바탕으로 이 개념들을 쉽게 이해할 수 있도록 설명하려고 한다.


1. Prototype의 역할

JavaScript는 프로토타입 기반 상속을 사용한다. 즉, 각 객체는 다른 객체로부터 속성이나 메서드를 상속받을 수 있는데, 이때 사용되는 것이 바로 prototype이다. 모든 함수(클래스 포함)는 생성될 때 prototype 객체를 가지고 있으며, 이 객체에 있는 메서드와 속성을 다른 객체들이 공유하게 된다.

class A {
  constructor() {
    this.name = 'Instance of A';
  }

  // 클래스에 메서드 정의
  b() {
    return `${this.name} can use method b!`;
  }
}

const c = new A();
console.log(c.b());  // "Instance of A can use method b!"

위 코드에서 A 클래스로부터 생성된 c 객체는 b() 메서드를 사용할 수 있다. 이는 c 객체가 A 클래스의 프로토타입에 정의된 b() 메서드를 상속받았기 때문이다.

중요한 사실

  • 프로토타입은 메모리 절약을 위해 사용된다. A 클래스로부터 생성된 모든 인스턴스는 하나의 b() 메서드를 공유한다. 즉, 인스턴스마다 별도로 메서드를 가지고 있지 않기 때문에 메모리 효율적이다.

2. __proto__의 역할

모든 JavaScript 객체는 __proto__라는 숨겨진 속성을 가지고 있다. 이 속성은 객체가 생성된 클래스의 prototype 객체를 가리키는 참조 링크이다. 객체에서 메서드나 속성을 찾을 때, 먼저 자신의 속성을 확인하고, 없으면 이 __proto__를 통해 상위 객체의 prototype에서 찾게 된다. 이 과정을 프로토타입 체인이라고 한다.

A.prototype.newMethod = function() {
  return `${this.name} can use the new prototype method!`;
}

console.log(c.newMethod());  // "Instance of A can use the new prototype method!"

이처럼 A.prototype에 newMethod()를 추가하면, 이미 생성된 c 인스턴스에서도 해당 메서드를 사용할 수 있게 됩니다. 이게 바로 프로토타입 기반 상속의 기능이다.


3. 상속과 프로토타입 체인

JavaScript에서는 클래스 상속을 통해 상위 클래스의 메서드를 하위 클래스에서 재사용할 수 있다. 이때도 프로토타입 체인이 작동하여 상위 클래스의 메서드를 찾아 실행한다.

class B extends A {
  constructor() {
    super();  // A 클래스의 생성자를 호출
    this.type = 'Instance of B';
  }

  c() {
    return `${this.type} can use method c!`;
  }
}

const d = new B();
console.log(d.b());  // "Instance of A can use method b!"
console.log(d.c());  // "Instance of B can use method c!"

위 예시에서 B 클래스는 A 클래스를 상속받는다. B 클래스로 생성된 인스턴스 d는 프로토타입 체인을 통해 A 클래스의 b() 메서드를 호출할 수 있다.


4. 정리

  • prototype은 JavaScript의 객체 상속을 구현하는 핵심 개념이다. 객체가 특정 메서드를 직접 가지고 있지 않더라도, 그 객체의 프로토타입 체인을 통해 상속받은 메서드를 사용할 수 있다.
  • __proto__는 객체가 자신의 프로토타입을 참조할 때 사용하는 속성이다. 객체의 속성이나 메서드를 찾을 때, __proto__를 따라가며 프로토타입 체인을 통해 상위 객체의 속성을 찾는다.