클래스 기반 언어가 상속을 사용한다면
프로토타입 기반 언어는 어떤 객체를 원형(prototype)으로 삼고, 이를 복제(참조)하여 상속과 비슷한 효과를 갖는다.
자바스크립트 또한 프로토타입 기반 언어이다!
const instance = new Constructor();
어떤 생성자 함수(Constructor)를 new 연산자와 함께 호출하면
Constructor에서 정의된 내용을 바탕으로 새로운 인스턴스(instance)가 생성된다.
이 instance에는 __proto__라는 프로퍼티가 "자동 부여"되는데,
이 프로퍼티는 Constructor의 prototype이라는 프로퍼티를 참조한다!
즉, 인스턴스는 __proto__를 통해서 생성자함수의 prototype 프로퍼티에 접근할 수 있다.
> 예시
Developer라는 생성자 함수의 prototype에 getName이라는 메서드를 지정했을때
/* 생성자 함수 생성 */
const Developer = function (name) {
this.name = name;
};
/* 프로토타입에 getName 메서드 지정 */
Developer.prototype.getName = function () {
return this.name;
};
Developer의 인스턴스는 __proto__를 통해서 getName 프로퍼티에 접근할 수 있다.
const instance = new Developer("Wooyoung");
Developer.prototype === instance.__proto__; // true
instance.__proto__.getName(); // undefined ⭐️
/* __proto__는 생략가능한 프로퍼티 */
instance.getName(); // Wooyoung ⭐️⭐️
⭐️
undefined가 나오는 이유는 this에 바인딩 대상이 잘못 지정되었기 때문이다.
함수를 메서드로서 호출했는데 this가 instance가 아닌 prototype 객체(instance.__proto__)를 가리키고 있다.
instance 내부에는 name 프로퍼티가 존재하지만
prototype 객체(instance.__proto__) 내부에는 name 프로퍼티가 없으므로 undefined를 반환하는 것이다.
(prototype 상에는 name 프로퍼티가 없으므로)
c.f) prototype 객체에 직접 name 프로퍼티를 추가하면 정상적으로 출력되기는 한다.
하지만 이때 this가 instance가 아닌
prototype 객체(instance.__proto__)를 바라보고 있으므로 좋은 방법은 아니다..
const instance = new Developer("Wooyoung");
/* prototype 객체에 직접 name 프로퍼티를 추가 */
instance.__proto__.name = "Wooyoung"; // 또는 Developer.prototype.name = "Wooyoung";
instance.__proto__.getName(); // Wooyoung
c.f) 명시적으로 this를 바인딩하는 call, apply 함수를 활용해도 해결은 가능하다!
const instance = new Developer("Wooyoung");
instance.__proto__.getName(); // undefined
instance.__proto__.getName.call(instance); // Wooyoung
⭐️⭐️
__proto__는 생략가능한 프로퍼티이기 때문에
instance.getName()으로 호출 시, 우리가 원하는 this바인딩이 되어 값을 얻을 수 있다.
(instance.__proto__에 있는 getName 메서드를 실행하지만 this는 instance를 바라보는 것!)
결국 우리가 실무든 프로젝트든 알게모르게 __proto__가 생략된 채로 사용하고 있었을 것이다🤔
> 정리
new 연산자로 Constructor를 호출하면 instance가 만들어지는데,
이 instance의 생략 가능한 프로퍼티인 __proto__는 Constructor의 prototype을 참조한다!
자바스크립트는 함수에 자동으로 prototype 프로퍼티를 생성해 놓는데
new 연산자와 함께 생성자 함수로 사용할 경우,
그로부터 생성된 인스턴스에는 숨겨진 __proto__ 프로퍼티도 자동으로 생성된다고 한다!
__proto__ 프로퍼티는 생략가능하도록 구현돼 있기 때문에
생성자 함수의 prototype에 어떤 메서드나 프로퍼티가 있다면
인스턴스에서도 마치 자신의 것처럼 해당 메서드나 프로퍼티에 접근할 수 있게 된다.
'JavaScript' 카테고리의 다른 글
프로토타입(prototype) - constructor 프로퍼티 (0) | 2022.05.29 |
---|---|
프로토타입(prototype) 디렉터리 구조 (0) | 2022.05.28 |
커링 함수 (0) | 2022.05.21 |
클로저 활용 예시 (2) (0) | 2022.05.01 |
클로저 활용 예시 (1) (0) | 2022.03.31 |
댓글