자바스크립트는 프로토타입 기반 언어이다
생성자 함수(클래스)의 prototype 프로퍼티
- 여기서 프로토타입이란 모든 객체들이 상위 객체의 속성과 메서드를 상속받기 위한 프로토타입 객체를 가진다는 의미이다.
- 생성자 함수를 포함한 모든 자바스크립트의 함수(객체)는 prototype이라는 속성을 갖는다.
- 이 prototype 속성/프로퍼티에 인스턴스 객체들에게 상속시켜줄 수 있는 혹은, 인스턴스 객체가 접근할 수 있는 모든 프로퍼티와 메서드들이 저장된다.
- 생성자 함수로 만들어진 인스턴스는 이 프로토타입을 상속받는다.
class Person {
constructor(firstName, birthYear) {
this.firstName = firstName;
this.birthYear = birthYear;
}
}
const hyejung = new Person('hyejung', 1997);
- 위 예시처럼 Person이라는 클래스 (생성자 함수)를 통해 생성된 hyejung 이라는 인스턴스 객체가 있다고 하자.
- 앞서 설명한 바와 같이 생성자 함수는 prototype 이라는 프로퍼티를 가지고 있다. 생성자 함수에서 설정된 프로퍼티나 메소드가 이 prototype이라는 프로퍼티에 저장이 된다면, 아래와 같이 새롭게 메서드를 추가해줄 수 있다.
Person.prototype.calcAge = function () {
console.log(2037 - this.birthYear);
};
- hyejung이라는 인스턴스는 이 프로토타입 프로퍼티를 상속받아 해당 메서드 calcAge를 사용할 수 있다.
hyejung.calcAge(); //40
인스턴스 객체의 __proto__ 프로퍼티
- 모든 객체는 자신의 "프로토타입"을 확인할 수 있는 __proto__라는 프로퍼티가 존재한다. (인스턴스 객체의 "프로토타입"과 생성자 함수의 prototype 프로퍼티는 서로 다른 "개념"임을 유의하자.)
- 콘솔로 인스턴스 객체 hyejung의 __proto__ 프로퍼티를 살펴보면, 앞서 생성자 함수 프로토타입 프로퍼티에 추가해 주었던 calcAge 라는 메서드가 나온다.
console.log(hyejung.__proto__);
// { calcAge: [Function (anonymous)] }
- 하지만 이 인스턴스 객체에 실제로 calcAge라는 메서드(프로퍼티)가 존재하는지 살펴보면 그렇지 않다고 나온다.
console.log(hyejung.hasOwnProperty('calcAge'));
//false
- 이 것의 의미는 무엇일까? 어떤 인스턴스 객체의 프로토타입이라는 것은, 생성자 함수의 prototype 프로퍼티라는 것이다. prototype 프로퍼티를 통해 인스턴스 객체에게 프로토타입이 상속되고, 인스턴스는 이 프로토타입(객체)를 통해 자신에게 실제로 존재하는 프로퍼티는 아니지만, 상속받아서 혹은 프로토타입에 위임하여 이 것에 접근할 수 있는 것이다.
- 아래 결과를 보면 더 명확하게 알 수 있다.
console.log(hyejung.__proto__ === Person.prototype); // true
console.log(Person.prototype.isPrototypeOf(hyejung)); // true
- 정리하자면, Person.prototype 프로퍼티가 인스턴스인 hyejung의 프로토타입이 되는 것이다.
- 어떻게 이런 것이 가능할까? new 연산자로 새로운 인스턴스를 생성할 때, 인스턴스 생성 과정에서 먼저 생성된 빈 객체 { }가 프로토타입 객체에 연결이 되는 과정에서, __proto__ 프로퍼티를 생성하고 이 값을 생성자 함수의 prototype 프로퍼티로 셋팅한다.
- 추가적으로 메서드 뿐만이 아니라 상속될 프로퍼티도 프로토타입 프로퍼티를 통해 정의할 수 있다.
Person.prototype.species = 'Homo Sapiens';
console.log(hyejung.__proto__);
// { calcAge: [Function (anonymous)], species: 'Homo Sapiens' }
// 실제로 존재하지 않는, 상속받은 프로퍼티임을 확인할 수 있다.
console.log(hyejung.hasOwnProperty('species')); //false
+ 참고로 모든 객체가 프로토타입을 갖는 다는 것은 한 인스턴스의 부모 객체도 프로토 타입을 갖고, 그 부모 객체의 부모 객체도 프로토타입으로부터 상속을 받는다는 의미이다. 이렇게 계속해서 참조하는 것을 프로토타입 체인이라고 한다.
//Person 생성자 함수도 Function 클래스의 프로토타입을 상속받는다.
console.log(Person.__proto__ === Function.prototype) //true
클래스, 프로토타입, 인스턴스의 관계
이렇게 프로토타입을 활용해 각 객체에 속성과 메서드를 상속시켜 줄 수 있기 때문에, 클래스를 작성할 때 직접 모든 프로퍼티를 입력하여 인스턴스를 생성하지 말고 프로토타입 프로퍼티에 등록하여 생성하는 것이 좋다. 모든 인스턴스 객체들이 다 똑같은 메서드를 실제로 가지고 있다면 엄청 비효율적일 것이다.
'JavaScript > JavaScript' 카테고리의 다른 글
[JavaScript] 클래스간의 상속 (프로토타입 상속) (0) | 2022.07.25 |
---|---|
[JavaScript] 프로토타입 체인 (0) | 2022.07.25 |
[JavaScript] OOP in JavaScript : 생성자 함수, 클래스 문법 (0) | 2022.07.22 |
[JavaScript] 객체지향 프로그래밍 : OOP란 무엇인가? (0) | 2022.07.22 |
[JavaScript] 클로저와 커링 초간단 정리 (0) | 2022.07.21 |