📃 Prototype

📍 프로토타입 (Prototype)

  • 자바스크립트의 모든 객체는 자신의 부모 역할을 담당하는 객체와 연결되어 있다. 이러한 부모 객체를 프로토타입 객체 또는 프로토타입이라고 한다.

  • 프로토타입은 객체의 원형이라는 뜻으로, 객체는 부모가 가지는 유전자 즉, 프로토타입 객체로부터 프로퍼티 또는 메소드를 상속 받는다.

  • 다시 말해, 객체는 다른 객체로부터 직접 상속을 받는데, 이때 상속되는 객체가 프로토타입이다.

  const carPrototype = {
    color: function () {
      console.log('black color');
    },
  };

  function Car() {}

  Car.prototype = carPrototype;

  const miniCar = new Car();

  miniCar.color(); // 출력: black color

코드 설명
  1. carPrototype은 프로토타입의 객체로, Car 생성자 함수의 prototype에 할당되어 있다.
  1. miniCar라는 인스턴스는 Car 생성자 함수로 생성되었는데, 이로 인해 miniCarcarPrototype에 있는 color 메소드를 상속받아 사용할 수 있다.


✔️ Prototype 사용 이유

  • 우리는 왜 Prototype을 굳이 사용하는 걸까?

    생성자 함수로 객체를 생성할 때, 새로운 객체가 생성되면 객체 내의 프로퍼티와 메소드가 모든 인스턴스마다 중복해서 생성돼 비효율적이다.

    이는 메모리 낭비로 이어지기에 프로토타입을 사용하면 해당 메소드나 프로퍼티를 모든 인스턴스가 공유하게 되므로, 부모 객체 생성 시 한 번만 생성되어 메모리를 절약할 수 있다.


📍 prototype 프로퍼티

  • 함수 객체에서는 prototype이라는 특수한 프로퍼티가 존재한다. ( 객체 !== 프로퍼티 )

  • 이 프로퍼티에는 해당 함수로 생성된 인스턴스들이 공통적으로 가지는 속성이나 메소드가 포함되어 있다.

  function Car(make, model) {
    this.make = make;
    this.model = model;
  }

  Car.prototype.drive = function () {
    console.log('Driving a', this.make, this.model);
  };

  const myCar = new Car('Hyundai', 'Grandeur');

  myCar.drive(); // 출력: Driving a Hyundai Grandeur

코드 설명
  1. Car 생성자 함수의 prototype 프로퍼티drive 메소드를 추가했다.
  1. 이 메소드는 Car 생성자 함수로 생성된 모든 인스턴스에서 공통으로 사용할 수 있다.


✔️ prototype vs __proto__ 관계

  • 상속이 .prototype 프로퍼티를 통해서 가능하다면, 인스턴스는 자신의 프로토타입을 .__proto__를 통해서 가능하다.

  • .prototype 프로퍼티는 내가 원형일 때 존재하며, 함수 객체만 가지고 있다. 주로 생성자 함수에서 사용하고, 해당 생성자로부터 생성된 모든 인스턴스가 공유하는 프로퍼티와 메소드를 정의한다.

  • .__proto__는 나의 원형을 가리키고, 모든 객체가 가지고 있다. 프로토타입 체인에서 현재 객체의 부모를 가리키는 링크 역할을 하며, 객체 간의 상속 구조를 형성하는 중요한 역할을 한다.

  function Car(color) {
    this.color = color;
  }

  const myCar = new Car('black');

  console.dir(Car);    // prototype 프로퍼티가 있다.
  console.dir(myCar);  // prototype 프로퍼티가 없다.

코드 설명
  1. Car는 생성자 함수이며, 객체를 생성하고 초기화한다. myCarCar 생성자 함수를 통해 생성된 인스턴스다.
  1. 콘솔을 통해 Car 함수 객체를 살펴보면, prototype 프로퍼티가 존재한다. 왜냐? 생성자 함수가 가지는 특수한 프로퍼티로 해당 함수로 생성된 인스턴스들이 공유하는 프로토타입을 지정하기 때문이다.
 console.log(Car.prototype === myCar.__proto__);
  1. 하지만 콘솔을 통해 myCar 인스턴스를 살펴보면, prototype 프로퍼티가 존재하지 않는다. 인스턴스 자체에 prototype 프로퍼티가 직접 존재하지 않는 대신, 인스턴스는 __proto__를 통해 프로토타입에 접근할 수 있다.
 console.log(Car.__proto__ === Function.prototype);



📍 프로토타입 체인 (Prototype Chain)

  • 인스턴스 객체에서 어떤 프로퍼티에 접근하려고 할 때, 해당 객체에 그 프로퍼티가 없으면 프로토타입 체인을 따라 상위 프로토타입으로 올라가서 찾는다.

  • 이를 통해 상속 구조를 형성하며 부모 객체의 속성이 자식 객체에게 상속된다.

  const bigCarPrototype = {
    start: function () {
      console.log('BigCar starting');
    },
  };

  const miniCarPrototype = Object.create(bigCarPrototype);
  miniCarPrototype.drive = function () {
    console.log('MiniCar driving');
  };

  const myCars = Object.create(miniCarPrototype);

  myCars.drive(); // 출력: MiniCar driving
  myCars.start(); // 출력: BigCar starting

코드 설명
  1. bigCarPrototype은 부모 객체이고, miniCarPrototype은 자식 객체이며, Object.create를 사용해 프로토타입 체인을 만들었다.
  1. 자, 이제 myCars 인스턴스는 miniCarPrototype을 프로토타입으로 가지며, drive 메소드를 직접 상속받고, start 메소드는 bigCarPrototype을 통해 간접적으로 상속받아 사용할 수 있다.


profile
할 수 있다고 믿는 사람은 결국 그렇게 된다 😄😊

0개의 댓글

Powered by GraphCDN, the GraphQL CDN