이 글을 공부하면서 번역하고 정리한 글입니다.
같은 타입의 여러 객체들 간 속성을 공유하는 패턴
prototype 패턴은 같은 타입의 여러 객체 간 속성을 공유하기 좋습니다. 프로토타입은 JavaScript의 native 객체이며 프로토타입 체인을 통해 객체에 접근할 수 있습니다.
우리는 하나의 애플리케이션에서 같은 타입의 객체를 많이 만들어 사용합니다. 이때, ES6의 클래스의 인스턴스를 여러개 만들어 사용합니다.
Example
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");
ES6 클래스를 사용하면 클래스에 정의된 모든 속성들은 위 예제에서는 'bark'라는 함수는 자동으로 프로토타입에 추가됩니다.
console.log(Dog.prototype);
// constructor: ƒ Dog(name, breed) bark: ƒ bark()
console.log(dog1.__proto__);
// constructor: ƒ Dog(name, breed) bark: ƒ bark()
생성자의 prototype이나 클래스의 인스턴스의 __proto__를 통해 프로토타입을 직접 확인할 수 있습니다. 클래스 인스턴스의 __proto__ 값은 생성자의 프로토타입을 직접 참조합니다! 객체에 존재하지 않는 속성에 직접 접근하려고 하면 JavaScript는 프로토타입 체인을 타고 내려가 해당 속성이 프로토타입 체인 내에서 존재하는 것인지 확인합니다.
프로토타입 패턴은 같은 속성에 접근해야 하는 객체들을 다룰 때 유용합니다. 모든 인스턴스들이 하나의 프로토타입 객체에 접근할 수 있기 때문에 매번 속성을 복제하는 대신, 프로토타입에 속성을 추가하면 됩니다. 인스턴스를 이미 생성한 이후에도 속성을 추가하기가 쉽습니다.
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.prototype.play = () => console.log("Playing now!");
dog1.play();
이와 같이 Dog.prototype에 play라는 속성을 추가할 수 있습니다.
프로토타입 체인이라는 말은 한 단계 이상이 존재할 수 있다는 것을 의미합니. 위에서 인스턴스의 __proto__ 값으로 접근할 수 있는 속성들을 살펴보습니다. 하지만 프로토타입은 프로토타입 자체도 __proto__ 객체를 가지고 있습니다.
또 다른 예제로 SuperDog라는 클래스를 만들어봅시다! 이것은 위에서 만든 Dog라는 클래스를 상속하면서 fly라는 속성이 추가됩니다.
class SuperDog extends Dog {
constructor(name) {
super(name);
}
fly() {
return "Flying!";
}
}
Daisy라는 SuperDog 인스턴스를 만들어서 Dasiy가 bark하거나 fly하게 해봅시다!
class Dog {
constructor(name) {
this.name = name;
}
bark() {
console.log("Woof!");
}
}
class SuperDog extends Dog {
constructor(name) {
super(name);
}
fly() {
console.log(`Flying!`);
}
}
const dog1 = new SuperDog("Daisy");
dog1.bark();
dog1.fly();
SuperDog는 Dog 클래스를 상속했기 때문에 bark 메소드에 접근할 수 있습니다. 그리고 SupoerDog의 프로토타입의 __proto__ 값은 Dog.prototype 객체를 참조합니다.
이제 왜 포로토타입 체인이라고 부르는지 이해가 되죠? 객체에 직접 존재하지 않는 속성에 접근하려 할 때 JavaScriptsms 객체의 __proto__ 값이 가리치는 객체들을 타고 올라가면서 해당 속성을 찾는 것입니다.
Object.create
Object.create 메소드는 프로토타입에 값을 직접 전달하여 새로운 객체를 만드는데 사용합니다.
const dog = {
bark() {
return `Woof!`;
},
};
const pet1 = Object.create(dog);
pet1은 아무런 속성도 가지고 있지 않지만, 프로토타입 체인에 있는 속성들에 접근할 수 있습니다. pet1의 프로토타입에 dog 객체를 전달했기 때문에 pet1은 bark 메소드에 접근할 수 있습니다.
const dog = {
bark() {
console.log(`Woof!`);
}
};
const pet1 = Object.create(dog);
pet1.bark(); // Woof!
console.log("Direct properties on pet1: ", Object.keys(pet1)); // Direct properties on pet1:
[]
console.log("Properties on pet1's prototype: ", Object.keys(pet1.__proto__)); // Properties on pet1's prototype:
(1) ["bark"]
Object.create는 새로 생성할 객체의 프로토타입을 직접 명시하여 어떤 객체에서 다른 객체로 속성을 직접 상속하는 간단한 방법입니다. 그렇게 생성된 객체는 프로토타입 체인을 타고 새로운 속성에 접근할 수 있습니다.
프로토타입 패턴은 객체가 다른 객체의 속성에 접근하거나 상속하기 쉽게 만들어줍니다. 프로토타입 체인은 객체 자체에 직접 정의되지 않은 속성에 접근할 수 있게 만들기 때문에 메소드나 속성을 중복해서 정의하지 않게 해주고 이로 인해 메모리 사용을 감소하게 해줍니다.
'웹 개발' 카테고리의 다른 글
디자인 패턴) Container/Presentational Pattern (0) | 2023.07.17 |
---|---|
디자인 패턴) Provider Pattern (0) | 2023.07.12 |