자바스크립트의 프로토타입(Prototype)은 객체 지향 프로그래밍을 구현하는데 핵심적인 개념입니다. 자바스크립트는 프로토타입 기반 상속을 사용하며, 이를 통해 객체와 함수가 프로토타입 체인을 통해 서로 상호작용하고 상속 관계를 형성할 수 있습니다.
1. 프로토타입의 기본 개념
자바스크립트의 모든 객체는 다른 객체로부터 메서드와 속성을 상속받기 위해 __proto__
(또는 [[Prototype]]
)라는 숨겨진 속성을 가집니다. 이는 프로토타입 체인을 형성하여 객체의 상속 관계를 정의합니다.
1.1 객체 생성과 프로토타입
객체 리터럴로 생성된 객체의 프로토타입은 Object.prototype
입니다.
const obj = {};
console.log(obj.__proto__ === Object.prototype); // true
생성자 함수로 생성된 객체는 해당 생성자 함수의 prototype
속성을 프로토타입으로 갖습니다.
function Person(name) {
this.name = name;
}
const person = new Person('Alice');
console.log(person.__proto__ === Person.prototype); // true
1.2 프로토타입 체인
객체가 특정 속성이나 메서드를 찾지 못하면 프로토타입 체인을 따라가면서 검색을 계속합니다. 최종적으로 Object.prototype
까지 검색을 시도하고, 그래도 찾지 못하면 undefined
를 반환합니다.
const obj = { a: 1 };
console.log(obj.toString()); // [object Object] (Object.prototype의 메서드)
console.log(obj.hasOwnProperty('a')); // true (Object.prototype의 메서드)
2. 생성자 함수와 프로토타입
생성자 함수는 새로운 객체를 만들 때 그 객체의 프로토타입을 정의합니다. 모든 생성자 함수는 prototype
속성을 가지며, 이 속성은 해당 생성자 함수로 생성된 모든 객체의 프로토타입이 됩니다.
function Animal(type) {
this.type = type;
}
Animal.prototype.speak = function() {
console.log(`The ${this.type} makes a sound`);
};
const dog = new Animal('dog');
dog.speak(); // The dog makes a sound
위 예제에서 speak
메서드는 Animal.prototype
에 정의되어 있으며, dog
객체에서 사용할 수 있습니다.
3. 프로토타입 상속
프로토타입 상속을 통해 객체는 다른 객체의 속성과 메서드를 상속받을 수 있습니다. 이를 통해 재사용성과 코드의 유지보수성을 높일 수 있습니다.
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
console.log(`Hello, my name is ${this.name}`);
};
function Student(name, grade) {
Person.call(this, name); // Person 생성자 함수 호출
this.grade = grade;
}
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
Student.prototype.study = function() {
console.log(`${this.name} is studying`);
};
const student = new Student('Alice', 'A');
student.greet(); // Hello, my name is Alice
student.study(); // Alice is studying
위 예제에서 Student
는 Person
을 상속받아 greet
메서드를 사용할 수 있으며, 추가로 study
메서드를 정의하여 사용할 수 있습니다.
4. 프로토타입의 동적 변경
프로토타입은 동적으로 변경될 수 있으며, 이는 모든 인스턴스에 영향을 미칩니다.
function Car(model) {
this.model = model;
}
const car1 = new Car('Toyota');
const car2 = new Car('Honda');
Car.prototype.drive = function() {
console.log(`${this.model} is driving`);
};
car1.drive(); // Toyota is driving
car2.drive(); // Honda is driving
Car.prototype.drive = function() {
console.log(`${this.model} is moving`);
};
car1.drive(); // Toyota is moving
car2.drive(); // Honda is moving
위 예제에서 Car.prototype.drive
를 동적으로 변경하면, car1
과 car2
모두 변경된 drive
메서드를 사용합니다.
5. ES6 클래스와 프로토타입
ES6 클래스 문법은 프로토타입 기반 상속을 더욱 간결하고 직관적으로 사용할 수 있게 합니다. 클래스는 사실상 프로토타입을 사용하는 문법적 설탕입니다.
class Animal {
constructor(type) {
this.type = type;
}
speak() {
console.log(`The ${this.type} makes a sound`);
}
}
class Dog extends Animal {
constructor(type, name) {
super(type); // 부모 클래스 생성자 호출
this.name = name;
}
bark() {
console.log(`${this.name} is barking`);
}
}
const dog = new Dog('dog', 'Rex');
dog.speak(); // The dog makes a sound
dog.bark(); // Rex is barking
위 예제에서 Dog
클래스는 Animal
클래스를 상속받아 speak
메서드를 사용하고, 추가로 bark
메서드를 정의합니다.
6. 프로토타입 메서드와 인스턴스 메서드
프로토타입 메서드는 모든 인스턴스가 공유하는 메서드입니다. 반면, 인스턴스 메서드는 각 인스턴스마다 개별적으로 존재합니다.
function Gadget(name) {
this.name = name;
this.sayName = function() {
console.log(this.name);
};
}
Gadget.prototype.sayHello = function() {
console.log(`Hello, ${this.name}`);
};
const gadget1 = new Gadget('Phone');
const gadget2 = new Gadget('Tablet');
gadget1.sayHello(); // Hello, Phone
gadget2.sayHello(); // Hello, Tablet
gadget1.sayName(); // Phone
gadget2.sayName(); // Tablet
위 예제에서 sayHello
는 프로토타입 메서드로 모든 인스턴스가 공유하지만, sayName
은 인스턴스 메서드로 각 인스턴스마다 개별적으로 존재합니다.
7. 프로토타입 상속과 Object.create
Object.create
메서드는 특정 객체를 프로토타입으로 가지는 새로운 객체를 생성합니다.
const person = {
greet() {
console.log('Hello');
}
};
const friend = Object.create(person);
friend.greet(); // Hello
위 예제에서 friend
객체는 person
객체를 프로토타입으로 가지며, greet
메서드를 상속받습니다.
8. 프로토타입 체인의 예
function A() {}
function B() {}
B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;
const b = new B();
console.log(b instanceof A); // true
console.log(b instanceof B); // true
위 예제에서 b
객체는 B
와 A
모두의 인스턴스입니다. 이는 프로토타입 체인을 통해 이루어집니다.
9. 정적 메서드와 프로토타입 메서드
클래스에서 정적 메서드는 인스턴스가 아니라 클래스 자체에 속하는 메서드입니다.
class MyClass {
static staticMethod() {
console.log('This is a static method');
}
instanceMethod() {
console.log('This is an instance method');
}
}
MyClass.staticMethod(); // This is a static method
const myInstance = new MyClass();
myInstance.instanceMethod(); // This is an instance method
위 예제에서 staticMethod
는 클래스 자체에서 호출되며, instanceMethod
는 인스턴스에서 호출됩니다.
결론
자바스크립트의 프로토타입 개념은 객체 지향 프로그래밍을 구현하는 데 중요한 역할을 합니다. 프로토타입을 이해하면 자바스크립트의 상속과 객체 생성 방식을 더 잘 이해하고, 효율적으로 활용할 수 있습니다. 프로토타입은 코드 재사용성과 성능을 개선하는 데 중요한 도구이며, 이를 잘 활용하면 더욱 강력하고 유연한 자바스크립트 코드를 작성할 수 있습니다.