JAN's History
프로토타입 체인과 객체 상속의 이해 본문
자바스크립트에서는 모든 것이 객체이며 각 객체는 프로토타입을 가지고 있는데요! 이 프로토타입은 현재 객체가 상속받는 속성 및 메소드를 담고 있습니다. 자바스크립트에서 모든 객체는 다른 객체로부터 상속을 받습니다. 이러한 상속 구조는 프로토타입 체인(prototype chain)을 통해 구현됩니다. 이번 글에서는 프로토타입 체인의 기본 개념, 프로토타입 속성과 상속 구조, 그리고 이를 활용한 효율적인 메서드 공유에 대해 자세히 살펴보겠습니다. 🙌
🎯 1. 프로토타입이란?
모든 자바스크립트 객체는 숨겨진 __proto__ 프로퍼티를 가지고 있습니다. 이 프로퍼티는 객체의 프로토타입을 가리키며, 객체의 메서드와 속성을 상속받기 위한 연결고리입니다. 프로토타입은 생성자 함수의 prototype 속성을 통해 정의할 수 있습니다.
⭐ 중요: 모든 함수는 prototype 속성을 가지며, 생성자 함수로 사용될 때 이 속성을 통해 만들어진 객체의 프로토타입을 결정합니다.
📝 예제 코드: 프로토타입 체인 구조 살펴보기
- 아래 코드에서는 Dog 생성자 함수를 통해 새로운 객체를 생성했습니다. 이때 Dog.prototype은 새로운 객체의 __proto__로 설정됩니다. 이를 통해 pome 객체는 Dog 생성자 함수의 프로토타입에 접근할 수 있게 됩니다.
function Dog(type, size) {
this.type = type;
this.size = size;
}
console.log(Dog.prototype);
console.log(Dog.prototype.constructor === Dog); // true
console.log(Dog.prototype.constructor.prototype === Dog.prototype); // true
const pome = new Dog('포메라니안', 'small');
console.log(pome.__proto__); // Dog.prototype을 가리킴
console.log(pome.__proto__ === Dog.prototype); // true
🎯 2. 프로토타입 체인과 상속 관계
자바스크립트에서 모든 객체의 최상위 프로토타입은 Object.prototype입니다. 프로토타입 체인을 따라가면서 메서드와 속성을 검색하는데, 해당 객체에 없는 경우 상위 프로토타입으로 검색을 이어나갑니다.
예시 이미지에서도 알 수 있듯, 모든 객체의 확장은 객체가 소유한 prototype Object를 통해 이루어지며 이 연결의 끝은 Object 객체의 prototype Object가 됩니다.
⭐ 헷갈릴만한 부분: prototype 프로퍼티는 Constructor가 가지는 프로퍼티입니다. 그리고 함수 객체만이 prototype의 프로퍼티를 가지고 있습니다. 그래서 pome 객체는 함수가 아닌 함수를 통해 만들어진 Object에서 확장된 단일 객체이기 때문에, prototype 프로퍼티를 가지고 있지 않습니다!
📝 예제 코드: 프로토타입 체인 확인하기
- 예제에서 Dog 함수는 Function의 인스턴스이므로 Function.prototype을 상속받습니다. 그리고 모든 함수의 프로토타입 체인은 Object.prototype으로 끝나게 됩니다. 이 구조를 통해 Dog > Function > Object 순으로 상속받는 프로토타입 체인을 형성합니다.
⭐ 중요: 모든 객체는 최종적으로 Object.prototype을 가리키므로, Object에 정의된 메서드들을 상속받아 사용할 수 있습니다.
console.log(Dog.__proto__ === Function.prototype); // true
console.log(Function.prototype.__proto__ === Object.prototype); // true
console.log(Dog.prototype.__proto__ === Object.prototype); // true
🎯 3. 프로토타입 메서드의 공유
생성자 함수 내부에 메서드를 직접 정의하면, 각 인스턴스가 자신의 메서드를 가지게 되어 메모리 사용에 비효율적일 수 있습니다. 이 문제를 해결하기 위해 프로토타입을 활용하면 모든 인스턴스가 동일한 메서드를 공유할 수 있습니다.
📝 예제 코드: 프로토타입에 메서드 추가하기
- 코드에서 color 메서드는 Dog.prototype에 정의되었기 때문에 모든 Dog 인스턴스가 메서드를 공유하여 사용합니다. 이를 통해 메모리 사용을 효율적으로 관리할 수 있습니다.
⭐ 중요: 프로토타입에 정의된 메서드는 인스턴스 자체에 포함되어 있지 않으며, 상속을 통해 접근합니다. 이때 hasOwnProperty 메서드를 사용하면 해당 속성이 객체 자체에 있는지 확인할 수 있습니다. hasOwnProperty가 true면 상속받는 것이고 false면 자신의 객체에 있는 것이라고 이해하면 편해요!
function Dog(type, size) {
this.type = type;
this.size = size;
}
Dog.prototype.color = function () {
return `${this.type}은 흰색입니다.`;
};
const maltese = new Dog('말티즈', 'Small');
const samoyed = new Dog('사모예드', 'Big');
console.log(maltese.color()); // "말티즈은 흰색입니다."
console.log(samoyed.color()); // "사모예드은 흰색입니다."
console.log(maltese.color === samoyed.color); // true
🎯 4. 프로토타입 체인 변경: getPrototypeOf와 setPrototypeOf
자바스크립트에서는 인스턴스를 만든 후 상속 대상을 바꿀 수가 있는데요. 다른 언어를 이미 배우셨던 분들이라면 조금 당황하실 수 도 있습니다..ㅎㅎ (저 또한 그랬기 때문) __proto__를 통해 객체의 프로토타입에 접근할 수 있지만, 더 명확한 방법으로 Object.getPrototypeOf와 Object.setPrototypeOf를 사용할 수 있습니다.
📝 예제 코드: 프로토타입 체인 변경하기
- 코드에서는 BigDog 인스턴스인 samoyed의 프로토타입을 Dog.prototype으로 변경했습니다. 이를 통해 기존의 BigDog 메서드를 대체하고 새로운 프로토타입 체인을 설정할 수 있습니다.
⭐ 중요: 프로토타입 체인을 변경하면 상속 관계도 바뀌게 되므로, 변경 시에는 구조와 의도를 명확히 해야 합니다.
function Dog5(type, size) {
this.type = type;
this.size = size;
};
function BigDog(type, size) {
this.type = type;
this.size = size;
}
const samoyed = new BigDog('사모예드', 'Big');
console.log(Object.getPrototypeOf(samoyed5) === BigDog.prototype); //true
Object.setPrototypeOf(samoyed, Dog5.prototype); // 프로토타입 변경
console.log(samoyed.color()); // "사모예드은 흰색입니다."
console.log(samoyed5.constructor === BigDog.constructor); //fasle -> true Dog5로 상속 대상이 바뀌었기 때문
console.log(samoyed5.constructor === Dog5); //true
console.log(maltese5.constructor === Dog5); //true
console.log(Object.getPrototypeOf(samoyed5) === BigDog.prototype); //false (변경했으므로)
console.log(BigDog.prototype === Dog5.prototype); //false
📌 결론
프로토타입 체인은 자바스크립트 객체의 상속을 구현하는 핵심 개념입니다. 생성자 함수의 prototype에 메서드를 정의하면 모든 인스턴스에서 해당 메서드를 공유할 수 있으며, 메모리를 효율적으로 사용할 수 있습니다. 또한, Object.getPrototypeOf와 Object.setPrototypeOf를 활용해 프로토타입 체인을 동적으로 변경할 수 있습니다. 이러한 프로토타입의 구조를 이해하는 것이 객체 지향 프로그래밍을 더 깊이 있게 활용하는 데 필수적입니다!
🛠 실무적인 팁
프로토타입 메서드를 사용해 객체 간의 메서드를 공유하고 메모리 사용을 최적화하면 좋겠죠? 하지만, 프로토타입 체인을 변경하는 것은 복잡한 버그를 유발할 수 있으므로 신중하게 사용해야 합니다. 😊
'Javascript' 카테고리의 다른 글
JavaScript의 Execution Context Stack (2) | 2024.10.31 |
---|---|
자바스크립트에서 this 키워드 이해하기 (0) | 2024.10.29 |
생성자 함수와 new.target을 이해해보자!_! (0) | 2024.10.23 |
불변 객체(Immutable Object)란? (0) | 2024.10.21 |
프로퍼티 어트리뷰트란(Property Attribute)? (0) | 2024.10.19 |