프로토타입? 핵심 요약
자바스크립트는 다른 언어들과는 다르게 클래스 개념이 없다. (물론 이후에는 생기지만, 초창기엔 없었다)
때문에 기존 객체를 복사하여 새로운 객체를 생성해만했고,
이러한 특징을 가진 언어라 프로토타입 기반 언어라고 칭하는 것이다.
프로토타입은 크게 프로토타입 객체를 참조하는 prototype 속성, 객체 멤버인 proto 속성이 참조하는 링크가 있다.
여기서 prototype 속성은 함수의 인스턴스가 가진다.
상속과 프로토 타입
상속
객체 지향 프로그래밍의 핵심 개념으로,
어떤 객체의 프로퍼티 또는 메서드를 다른 객체가 상속받아 그대로 사용할 수 있는 것을 말한다.
자바스크립트는 프로토타입을 기반으로 상속을 구현한다.
이로 인해 불필요한 중복을 제거할 수 있다.
// 생성자 함수
function Circle(radius) {
this.radius = radius;
this.getArea = function () {
return Math.PI * this.radius ** 2;
};
}
const c1 = new Circle(1);
const c2 = new Circle(2);
위 코드에서 Circle 생성자 함수가 생성하는 모든 객체는 radius 프로퍼티와 getArea 메서드를 가진다.
radius 는 일반적으로 인스턴스마다 다 다르겠지만,
getArea 메서드는 모든 인스턴스가 동일한 내용의 메서드를 사용하므로
하나만 생성해 모든 인스턴스가 공유하게끔 사용하는게 효율적이다.
만약 위 코드로 인스턴스를 100개 만들면, 메모리에 getArea 메서드도 100개 올라가 있을 것이다.
이를 상속으로 제거해보자.
function Circle(radius) {
this.radius = radius;
}
Circle.prototype.getArea = function () {
return Math.PI * this.radius ** 2;
};
const c1 = new Circle(1);
const c2 = new Circle(2);
자바스크립트는 프로토타입을 기반으로 상속을 구현한다.
Circle 생성자 함수가 생성한 모든 인스턴스는 자신의 프로토타입, 즉 부모 객체 역할을 하는
Circle.prototype의 모든 프로퍼티와 메서드를 상속받는다.
getArea 메서드는 단 하나만 생성되어 프로토타입인 Circle.prototype의 메서드로 할당되어 있다.
따라서 Circle 생성자 함수가 생성하는 모든 인스턴스는 getArea 메서드를 상속받아 사용할 수 있다.
결론적으로, prototype은 부모 객체 역할을 하는 상위 객체라는 것이다.
생성자 함수가 생성할 모든 인스턴스가 공통적으로 사용할 프로퍼티나 메서드를 프로토타입에 구현해두면
생성자 함수가 생성할 모든 인스턴스는 별도의 구현 없이 부모 객체인 프로토타입 자산을 공유해서 사용가능하다.
프로토타입 객체
프로토타입 객체(프로토타입) 은 결국 객체간 상속을 구현하기 위해 사용하는 것이다.
모든 객체는 [[Prototype]] 이라는 내부 슬롯을 가지고,
이 값은 프로토타입의 참조다.
[[Prototype]] 에 저장되는 프로토타입은 객체 생성 방식에 의해 결정된다.
즉, 객체가 생성될 때 객체 생성 방식에 따라 프로토타입이 결정되고 [[Prototype]]에 저장된다.
만약 객체 리터럴로 객체를 생성했다면, 해당 객체의 프로토타입은 Object.prototype 일 것이다.
생성자 함수를 이용해 객체를 생성했다면,
해당 객체의 프로토타입은 생성자 함수의 prototype 프로퍼티에 바인딩 되어 있는 객체이다.
모든 객체는 하나의 프로토타입을 가지지만 [[Prototype]] 내부 슬롯의 값이 null 인 객체는 프로토타입이 없다.
그리고 모든 프로토타입은 생성자 함수와 연결되어 있다.
[[Prototype]] 내부 슬롯에는 직접 접근할 수는 없고,
__proto__ 접근자 프로퍼티를 이용해서 자신의 [[Prototype]] 내부 슬롯이 가리키는 프로토타입에 간접적으로 접근할 수 있다.
프로토타입은 자신의 constructor 프로퍼티를 통해 생성자 함수에 접근할 수 있고,
생성자 함수는 자신의 prototype 프로퍼티를 통해서 프로토타입에 접근할 수 있다.
__proto__ 접근자 프로퍼티
모든 객체는 __proto__ 접근자 프로퍼티를 통해 자신의 프로토타입, 즉 [[Prototype]] 내부 슬롯에 간접적으로 접근할 수 있다.
여기서 짚고 넘어갈 점은, __proto__ 는 접근자 프로퍼티 라는 것이다.
접근자 프로퍼티는 자체적으로 값을 가지지는 않고, 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 사용하는
접근자 함수인 [[Get]], [[Set]] 프로퍼티 어트리뷰트로 구성된 프로퍼티다.
__proto__ 접근자 프로퍼티를 살펴보면, get, set 접근자 함수를 확인할 수 있다.
Object.prototype의 접근자 프로퍼티인 __proto__ 는 getter/setter 함수라고 불리는
접근자 함수를 통해 [[Prototype]] 내부 슬롯의 값, 즉 프로토타입을 얻거나 할당한다.
3번째 라인의 obj.__proto__ 를 보고 '오 ... 그럼 obj 는 __proto__ 프로퍼티를 가지고 있는건가?'
라고 생각하면 안된다.
__proto__ 접근자 프로퍼티는 객체가 직접 갖고 있는게 아닌 Object.prototype 의 프로퍼티다.
'Archive > Develop' 카테고리의 다른 글
[ 모던 자바스크립트 스터디 ] 왜 __proto__ 접근자 프로퍼티를 통해 접근하는가? (0) | 2022.10.02 |
---|---|
[ NestJS ] 의존성 문제 발생 케이스 기록 (0) | 2022.09.28 |
[ 모던 자바스크립트 스터디 ] 함수와 일급 객체 (1) | 2022.09.25 |
[ 모던 자바스크립트 스터디 ] 생성자 함수에 의한 객체 생성 (1) | 2022.09.24 |
[ 모던 자바스크립트 스터디 ] 프로퍼티 어트리뷰트 (0) | 2022.09.22 |