본문 바로가기
JavaScript

프로토타입(prototype)

by whoyoung90 2022. 5. 22.
반응형

클래스 기반 언어가 상속을 사용한다면

프로토타입 기반 언어는 어떤 객체를 원형(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

댓글