누가봐도 인생 1회차의 기록장

개발공부/JavaScript 책

코어 자바스크립트 #07 (프로토타입)

김놀먹 2021. 12. 8. 21:46

정말.. 다들 이걸 이해하고 사용하는 걸까.. (흐린 눈)

나만 몰라... 나만 지식 없어...... 


 

자바스크립트는 프로토타입prototype 기반 언어이다. 클래스 기반 언어에서는 '상속'을 사용하지만 프로토타입 기반 언어에서는 어떤 객체를 원형prototype으로 이를 복제(참조)함으로써 상속과 비슷한 효과를 얻는다. 유명한 프로그래밍 언어의 상당수가 클래스 기반인 것에 비교하면 프로토타입은 꽤나 독특한 개념이라 할 수 있다.

 

프로토타입의 개념 이해

constructor, prototype, instance

var instance = new Constructor();
  1. 어떤 생성자 함수Constructor 를 new 연산자와 함께 호출하면
  2. Constructor에서 정의된 내용을 바탕으로 새로운 인스턴스instance 가 생성된다.
  3. 이때 instance에는 __proto__라는 프로퍼티가 자동으로 부여(생략 가능)되는데, 
  4. 이 프로퍼티는 Constructor의 prototype이라는 프로퍼티를 참조한다.
  • prototype은 객체이고 이를 참고하는 __proto__ 역시 당연히 객체이다. protytpe 객체 내부에는 인스턴스가 사용할 메서드를 저장한다. 그러면 인스턴스에서도 숨겨진 프로퍼티인 __proto__를 통해 이 메서드에 접근할 수 있게 된다. 
  • __proto__는 생략 가능한 프로퍼티이기 때문에 생성자 함수의 prototype에 어떤 메서드나 프로퍼티가 있다면 인스턴스에서도 마치 자신의 것처럼 해당 메서드나 프로퍼티에 접근할 수 있게 된다. 

 

constructor 프로퍼티

생성자 함수의 프로퍼티인 prototype 객체 내부에는 constructor라는 프로퍼티가 있다. 인스턴스의 __proto__ 객체 내부에도 마찬가지이다. 이 프로퍼티는 단어 그대로 원래 생성자 함수(자기 자신)를 참조한다. 자신을 참고하는 프로퍼티를 뭐하러 가질까 싶지만 이 역시 인스턴스로부터 그 원형이 무엇인지 알 수 있는 수단이 되는 필요한 정보이다. 

 

프로토타입 체인

메서드 오버라이드 : 메서드 위에 메서드가 덮어씌워지는 경우

prototype 객체를 참조하는 __proto__를 생략하면 인스턴스는 prototype에 정의된 프로퍼티나 메서드를 마치 자신의 것처럼 쓸 수 있다. 그런데 만약 인스턴스가 동일한 이름의 프로퍼티 또는 메서드를 가지고 있다면 어떨까?

일반적으로 메서드가 오버라이드 된 경우에는 자신으로부터 가장 가까운 메서드에만 접근할 수 있지만, 그다음으로 가까운 __proto__의 메서드도 우회적인 방법을 통해서이긴 하지만 접근이 불가능한 것은 아니다. 

 

프로토타입 체인

__proto__는 생략 가능하기 때문에 배열이 array.prototype 내부의 메서드를 마치 자신의 것처럼 실행할 수 있다. 마찬가지로 object.prototype 내부의 메서드도 자신의 것처럼 실행할 수 있다. 생략 가능한 __proto__를 한 번 더 따라가면 object.prototype을 참조할 수 있기 때문이다.

 

프로토타입 체인prototype chain : 어떤 데이터의 __proto__ 프로퍼티 내부에서 다시 __proto__ 프로퍼티가 연쇄적으로 이어진 것

프로토타입 체이닝prototype chianing :  프로토타입 체인을 따라가며 검색하는 것 (메서드 오버라이드와 동일한 맥락)

 

객체 전용 메서드의 예외사항

어떤 생성자 함수이든 prototype은 반드시 객체이기 때문에 object.prototype이 언제나 프로토타입 체인의 최상단에 존재하게 된다. 따라서 객체에서만 사용할 메서드는 다른 여느 데이터 타입처럼 프로토타입 객체안에 정의할 수 없다. 객체에서만 사용할 메서드를 object.prototype 내부에 정의한다면 다른 데이터 타입도 해당 메서드를 사용할 수 있게 되기 때문.

 

다중 프로토타입 체인

다중 프로토타입 체인을 연결하는 방법은 __proto__가 가리키는 대상, 즉 생성자 함수의 prototype이 연결하고자 하는 상위 생정자 함수의 인스턴스를 바라보게끔 해주면 된다.