Prototype 패턴

Prototype 패턴은 동일 타입의 여러 객체들이 프로퍼티를 공유할 때 유용하게 사용한다. Prototype은 JavaScript 객체의 기본 속성이므로 Prototype 체인을 활용할 수 있다.

하나의 앱을 만들 때. 동일한 타입의 여러 객체를 만들어내곤 한다. ES6 의 클래스의 여러 인스턴스를 만들어 낼 때 유용하게 사용할 수 있다.

여러 강아지 클래스를 만들어 보자. 예제에서 강아지는 이름을 가지고 있고. 짖을 수 있다.

class Dog {
  constructor(name) {
    this.name = name
  }

  bark() {
    return `Woof!`
  }
}

const dog1 = new Dog('Daisy')
const dog2 = new Dog('Max')
const dog3 = new Dog('Spot')

Dog 클래스의 생성자에서는 name 프로퍼티를 가지고 있고 클래스 자체적으로는 bark 프로퍼티를 가지고 있다. ES6클래스를 사용하면 모든 프로퍼티는 클래스 자체에 선언되며 위의 코드에서 bark 는 자동으로 prototype 에 추가된다.

생성자의 prototype 프로퍼티 혹은 생성된 인스턴스의 __proto__ 프로퍼티를 통해 Prototype 객체를 확인할 수 있다.

console.log(Dog.prototype)
// constructor: ƒ Dog(name, breed) bark: ƒ bark()

console.log(dog1.__proto__)
// constructor: ƒ Dog(name, breed) bark: ƒ bark()

어떤 인스턴스던 __proto__ 의 값은 Prototype 객체를 가리킨다. 객체에 없는 프로퍼티에 접근하려 하는 경우 JavaScript는 이 프로퍼티가 나타날때 까지 prototype chain 을 거슬러 올라간다.

Prototype 패턴은 객체들이 같은 프로퍼티를 가져야 하는 경우 유용하게 쓰일 수 있다. 중복된 프로퍼티들이 존재하는 객체를 매번 생성하기 보다, Prototype에 프로퍼티를 추가하면 모든 인스턴스들이 Prototype 객체를 활용할 수 있다.

모든 인스턴스들이 Prototype에 접근 가능하기 때문에. 인스턴스를 만든 뒤에도 Prototype에 프로퍼티를 추가할 수 있다.

예제에서 강아지는 짖기만 가능했지만 놀 수도 있게 구현해 보자. Prototype 객체에 play 프로퍼티를 추가하여 가능하다.

Prototype “체인” 단어처럼 Prototype은 한 단계 이상도 존재할 수 있다. 지금까지 어떤 인스턴스의 proto 속성에 대해서 이야기 했지만 사실 Prototype 객체 자체도 proto속성을 가질 수 있다.

이제 다른 타입의 강아지를 만들어 보자. 이 강아지는 Dog 의 속성을 모두 가지고 있지만 하늘을 날 수 있다. 이 슈퍼 강아지는 Dog 클래스를 상속받아 fly 메서드를 구현하면 된다.

class SuperDog extends Dog {
  constructor(name) {
    super(name)
  }

  fly() {
    return 'Flying!'
  }
}

아래 예제에서는 Daisy 라는 강아지를 만들고 짖거나 하늘을 날 수 있게 하고 있다.

SuperDogDog 를 상속했다. 따라서 인스턴스 dog1 은 bark 메서드도 호출 할 수 있다. SuperDog 의 Prototype 객체의 proto 는 Dot.prototype을 가리키고 있다.

Prototype 체인이라 불리우는 이유가 명확해졌을것이다. 현재 객체에 없는 프로퍼티에 접근하려 하는 경우 JavaScript는 같은 이름의 프로퍼티를 찾을때까지 재귀적으로 객체의 proto 를 따라 거슬러 올라가게 된다.


Object.create

Object.create 메서드는 Prototype으로 쓰일 객체를 인자로 받아 새로운 객체를 만들어낸다.

const dog = {
  bark() {
    return `Woof!`
  },
}

const pet1 = Object.create(dog)

pet1 자체적으로는 아무런 프로퍼티도 없지만 dog 객체를 Prototype으로 사용하기 때문에 bark 메서드를 사용할 수 있다.

Object.create 는 단순히 객체가 다른 객체로부터 프로퍼티를 상속받을 수 있게 해 준다. 실행 결과로 생성되는 객체는 Prototype 체인으로 인해 인자로 넘어갔던 객체의 프로퍼티를 활용할 수 있는 것이다.


Prototype 패턴은 어떤 객체가 다른 객체의 프로퍼티를 상속받을 수 있도록 해 준다. Prototype 체인을 통해 해당 객체에 프로퍼티가 직접 선언되어 있지 않아도 되므로 메서드 중복을 줄일 수 있고 이는 메모리 절약으로 이어진다.

참조