1. prototype이란?
prototype은 자바스크립트에서 객체 지향 프로그래밍을 지원하는 핵심 메커니즘으로, 모든 함수와 객체가 공유할 수 있는 공통 속성 및 메서드를 정의하는 역할을 한다.
자바스크립트는 클래스 기반이 아닌 프로토타입 기반(prototype-based) 언어로, 모든 객체는 다른 객체를 상속받을 수 있는 프로토타입(prototype)을 가진다.
2. prototype을 활용한 동작 방식
(1) 프로토타입 체인(Prototype Chain)
객체가 특정 프로퍼티나 메서드를 찾을 때, 먼저 자신의 속성에서 찾고, 없으면 프로토타입 객체를 따라 거슬러 올라가면서 찾는 방식을 프로토타입 체인이라 한다.
function Person(name) {
this.name = name;
}
Person.prototype.greet = function () {
console.log(`Hello, my name is ${this.name}`);
};
const john = new Person("John");
hohn.greet(); // "Hello, my name is John"
// 'greet' 메서드는 'john' 객체에 직접 정의되지 않았지만,
// 'Person.prototype'에서 찾아 호출할 수 있다.
✅ john 객체에는 greet()가 직접 존재하지 않지만, 프로토타입을 따라 Person.prototype.greet에서 찾기 때문에 호출 가능하다.
(2) __proto__ vs prototype
구분 | 설명 |
prototype | 함수(생성자 함수)에만 존재하며, 해당 함수로 생성된 객체들이 상속받을 메서드 및 속성을 정의 |
__proto__ | 모든 객체에 존재하며, 해당 객체의 프로토타입을 가리킴 |
function Person(name) {
this.name = name;
}
// 생성자 함수의 prototype 속성
console.log(Person.prototype); // { greet: f, constructor: f }
// 객체의 __proto__ 속성
const jane = new Person("Jane");
console.log(jane.__proto__ === Person.prototype); // true
✅ jane.__proto__는 Person.prototype을 가리킨다. 즉, jane이 Person의 프로토타입을 상속받았음을 의미한다.
3. 프로토타입의 활용
(1) 생성자 함수를 활용한 객체 생성 및 상속
function Animal(name) {
this.name = name;
}
Animal.prototype.makeSound = function () {
console.log(`${this.name} is making a sound.`);
};
const dog = new Animal("Dog");
dog.makeSound(); // "Dog is making a sound."
✅ dog 객체에는 makeSound()가 직접 정의되지 않았지만, 프로토타입을 통해 Animal.prototype.makeSound를 호출할 수 있다.
(2) 프로토타입을 이용한 상속
function Animal(name) {
this.name = name;
}
Animal.prototype.makeSound = function () {
console.log(`${this.name} is making a sound.`);
};
function Dog(name, breed) {
Animal.call(this, name); // Animal 생성자 호출
this.breed = breed;
}
Dog.prototype = Object.create(Animal.prototype); // 프로토타입 상속
Dog.prototype.constructor = Dog; // constructor 재설정
Dog.prototype.bark = function () {
console.log(`${this.name} is barking!`);
};
const myDog = new Dog("Buddy", "Golden Retriever");
myDog.makeSound(); // "Buddy is making a sound."
myDog.bark(); // "Buddy is barking!"
✅ Dog가 Animal의 속성과 메서드를 상속받았으며, 추가적으로 bark() 메서드를 정의할 수 있다.
4. 클래스(ES6)에서의 프로토타입
ES6 class 문법은 내부적으로 프로토타입을 기반으로 동작한다.
class Animal {
constructor(name) {
this.name = name;
}
makeSound() {
console.log(`${this.name} is making a sound.`);
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // 부모 클래스의 생성자 호출
this.breed = breed;
}
bark() {
console.log(`${this.name} is barking!`);
}
}
const myDog = new Dog("Charlie", "Labrador");
myDog.makeSound(); // "Charlie is making a sound."
myDog.bark(); // "Charlie is barking!"
✅ class는 문법적으로 깔끔하지만, 내부적으로 여전히 프로토타입을 사용하여 동작한다.
5. 프로토타입을 이용한 성능 최적화
객체의 메서드를 매번 새롭게 생성하는 것이 아니라, 공통된 메서드는 prototype에 정의하여 메모리 사용을 줄일 수 있다.
function Car(model) {
this.model = model;
}
// 모든 객체가 공유하는 메서드
Car.prototype.drive = function () {
console.log(`${this.model} is driving.`);
};
const car1 = new Car("Tesla");
const car2 = new Car("BMW");
console.log(car1.drive === car2.drive); // true (같은 메서드를 공유)
✅ Car.prototype.drive는 모든 Car 객체에서 공유되므로 메모리 절약 가능하다.
6. prototype과 Object.prototype
모든 객체는 최상위 프로토타입인 Object.prototype을 상속받는다.
console.log({}.hasOwnProperty("name")); // false
console.log([].hasOwnProperty("length")); // true
✅ {}와 []도 결국 Object.prototype에서 hasOwnProperty를 찾을 수 있다.
7. 프로토타입을 활용한 커스텀 메서드 추가
Array.prototype.first = function () {
return this[0];
};
const arr = [10, 20, 30];
console.log(arr.first()); // 10
✅ 기본 Array 객체에 first() 메서드를 추가하여, 모든 배열에서 사용할 수 있게 만들었다.
⚠️ 내장 객체의 프로토타입을 직접 수정하는 것은 예상치 못한 문제를 일으킬 수 있으므로 주의가 필요하다.
8. 결론
- prototype은 객체들이 공통으로 사용할 메서드와 속성을 정의하는 방식이다.
- 프로토타입 체인을 통해 부모 객체의 속성과 메서드를 상속받는다.
- 메모리 절약과 성능 최적화를 위해 인스턴스마다 중복되는 메서드를 생성하는 대신, prototype에 추가하여 공유한다.
- ES6의 class 문법도 내부적으로는 prototype을 사용하여 동작한다.
- 직접 prototype을 활용하여 상속, 메서드 추가, 최적화 등을 수행할 수 있다.
🚀 즉, prototype을 이해하면 자바스크립트의 객체 지향 프로그래밍을 더 깊이 있게 활용할 수 있다!
'Javascript' 카테고리의 다른 글
🔍 자바스크립트 깊은 복사 vs 얕은 복사, 제대로 이해하기! (1) | 2025.03.16 |
---|---|
자바스크립트의 숨겨진 비밀 : 우리가 몰랐던 JS의 흥미로운 동작들 (1) | 2025.03.15 |
[ECMAScript] ES5와 ES6의 차이점 (1) | 2025.03.13 |
더 이상 var를 사용하지 않는 이유 (0) | 2023.09.08 |
break, continue, return 등 for문, 중첩for문, if문 제어 명령어 정리 (0) | 2023.08.31 |