프로토타입이란?
- JS는 프로토타입 기반 언어이다.
- 모든 객체는 메서드와 속성들을 상속 받기 위한 템플릿으로써 프로토타입 객체를 가진다.
- 프로토타입 객체도 또 다시 상위 프로토타입 객체로부터 메서드와 속성을 상속받을 수 있다. 그 상위 프로토타입 객체도 마찬가지이다. 이것을 프로토타입 체인(Prototype Chain)이라고 한다.
- 상속되는 속성과 메서드들은 정확히는 각 객체라 아니라 객체의 생성자의 prototype 속성에 정의되어 있다.
- JS에서는 객체 인스턴스와 프로토타입 간에 연결(생성자의 prototype속성에서 파생된 __proto__속성으로 객체 인스턴스에 구현하고 있다)이 구성되며 이 연결을 따라 프로토타입 체인을 타고 올라가며 속성과 메서드를 탐색한다.
** 객체의 prototype(Object.getPrototypeOf(obj))과 생성자함수의 prototype 프로퍼티의 차이를 알아야한다.
생성자 함수 Foobar()는 Object.getPrototypeOf(Foobar)로 호출할 수 있는 자신의 prototype을 가진다. 그러나 이것은 prototype 프로퍼티(Foobar.prototype)와는 다르다.
만약 새로운 인스턴스인 let fooInstance = new Foobar()를 만들면 foolInstance는 생성자 함수의 prototype 프로퍼티를 가질 것이다. 따라서 Object.getPrototypeOf(fooInstance) === Foobar.prototype 이다.
Person()을 생성자 함수로 해서 var person1을 선언하였다. 콘솔에 person1.을 치면 person1의 프로토타입 객체인 Person()에 정의된 멤버들(name, age, gender)를 볼 수 있다. 또한 watch, valueOf처럼 Person()의 프로토타입 객체인 Object에 정의된 다른 멤버들도 볼 수 있다. 이는 프로토타입 체인이 동작한다는 증거이다.
만약 위의 콘솔에서 실제로는 Object에 정의되어 있는 메서드를 person1에서 호출하면 어떻게 될까?
person1.valueOf()를 예로 들면
- 브라우저는 우선 person1 객체가 valueOf() 메서드를 가지고 있는지 체크한다.
- 없으므로 person1의 프로토타입 객체(Person() 생성자함수의 프로토타입)에 valueOf() 메서드가 있는지 검사한다.
- 여전히 없으므로 Person() 생성자의 프로토타입 객체의 프로토타입 객체(Object() 생성자의 프로토타입)가 valusOf()메서드를 가지고 있는지 체크한다. 찾았으므로 호출하면서 체인이 종료된다.
** 프토로타입 체인에서 한 객체의 메서드와 속성들이 다른 객체로 복사되는 것이 아니다. 체인을 타고 올라가면서 접근 할 뿐이다!
** 특정 객체의 프로토타입객체에 다이렉트로 접근하는 공식적인 방법은 없다. 그러나 __proto__속성을 통해 특정 객체의 프로토타입 객체에 접근할 수 있도록 구현해놓았다. 예를 들면 person1.__proto__ 또는 person1.__proto__.__proto__이다. person1.__proto__는 Person()의 프로토타입, person1.__proto__.__proto__는 Object()의 프로토타입이다.
프로토타입 프로퍼티(속성)(obj.prototype. ): 상속받은 멤버들이 정의된 곳
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object
Object - JavaScript | MDN
Object 생성자는 객체 래퍼(wrapper)를 생성합니다.
developer.mozilla.org
위의 MDN Object페이지에 가보면 좌측에 수많은 속성과 메서드들이 정의되어 있다. 스크린샷에서 person1이 상속받은 멤버들보다 훨씬 많다. 일부는 상속 되었지만 나머지는 아닌것이다. 왜일까?
정답은 상속받는 멤버들은 prototype속성에 정의되어 있기 때문이다.
Object. 로 시작하는게 아닌, Object.prototype. 으로 시작하는 것들이다. prototype 속성도 하나의 객체이며 프로토타입 체인을 통해 상속하고자 하는 속성과 메서드를 담아주는 버킷으로 주로 사용되는 객체이다.
예를 들어 Object.prototype.watch(), Object.prototype.valueOf() 등등은 생성자를 통해 새로 생성되는 인스턴스는 물론, Object.prototype을 상속 받는 객체라면 어떤 객체에서든지 접근가능하다.
Object.is(), Object.keys()와 같은 protytope버킷에 정의되지 않은 멤버들은 상속되지 않는다. 이것은 Object() 생성자에서만 사용할 수 있는 멤버이다.
Person.prototype은 커스텀 생성자 프로토타입이므로 아무것도 들어있지 않다.
Object.prototype은 Object를 상속받은 객체에서 사용 가능한 수 많은 메소드들이 Object의 prototype속성에 정의되어 있음을 알 수 있다. Strine, Date, Number 등의 전역객체들의 prototype들도 확인할 수 있다.
***중요사항***
prototype 프로퍼티(속성)은 현재 prototype객체를 가리킬 것이라고 생각하지만 그렇지 않다!! (현재 prototype은 __proto__로 접근할 수 있는 내장된 객체이다)
prototype은 상속하려는 멤버를 정의하는 객체를 포함하는 프로퍼티이다.
기본적인 prototype을 정리했는데, 더 공부하고 내용 추가!
'바닐라코딩 사전학습 > JS' 카테고리의 다른 글
window.onload() (0) | 2021.12.30 |
---|---|
underscore.js 라이브러리 (0) | 2021.12.28 |
Windows 객체 (0) | 2021.12.28 |
this의 4가지 역할 (0) | 2021.12.27 |
new 예약어 (0) | 2021.12.27 |