프로토타입
프로토타입
자바스크립트는 프로토타입 기반언어(prototype-based language) 다. 모든 객체들이 메소드와 속성들을 상속받기위해 프로토타입 객체(prototype object) 를 가진다는 뜻이다. 참조함으로써 상속받는 효과를 얻는다.
ex) new 연산자로 생성한 인스턴스에는 __proto__가 생성되고, __proto__는 생성자 함수의 prototype 프로퍼티를 참조한다.
prototype은 객체이며 이를 참조하는 __proto__ (dunder proto) 도 객체이다. prototype 객체 내부에는 인스턴스가 사용할 메서드를 저장하고 인스턴스에서도 숨겨진 __proto__ 프로퍼티를 통해 메스드들에 접근할 수 있게 된다.
(ES5 명세에서는 dunder proto가 아니라 [[proto]] 이라는 명칭으로 정의되어 있다. 이런 명세에도 불구하고 브라우저는 __proto__에 직접 접근하는 방식을 고수해서 ES6에서는 이를 브라우저에서 동작하는 레거시 코드에 대한 호환성 문제로 인정하게 되었다. 따라서, 실무에서는 dunder proto를 사용하지 않기를 권장한다. )
짙은색은 열거 가능한 프로퍼티, 옅은색은 열거할 수 없는 프로퍼티이다.
배열 리터럴과 Array에 대해 출력해보자.
constructor 프로퍼티
생성자 함수의 prototype 프로퍼티 객체 내부에는 constructor 라는 프로퍼티가 있다. (인스턴스의 dunder proto도 마찬가지) . 원래의 생성자함수(자기 자신)을 참조하며, 인스턴스로부터 원형이 무엇인지 알 수있는 수단이기때문에 필요한 정보이다.
프로토타입 체이닝
자바스크립트 엔진이 자신의 프로퍼티를 검색해서 메소드와 속성들 (프로퍼티)가 있으면 실행하고 없으면 상위 프로토타입 객체의 __proto__를 검색하고 없으면 그 상위 프로토타입객체의 __proto__를 검색해서 실행하는 과정을 프로토타입 체이닝이라고 한다.
* 한 객체의 프로퍼티가 다른 객체로 복사되는것이 아니고 체인을 타고 올라가면서 검색하는 과정이다.
메서드 오버라이드
prototype 객체를 참조하는 dunder proto를 생략하면 인스턴스는 prototype에 정의된 프로퍼티나 메서드를 사용할 수있다. 만약 인스턴스가 동일한 이름의 프로퍼티 혹은 메서드를 가지고있다면 어떻게될까?
자바스크립트 엔진이 메서드를 찾는 방식은 자신의 프로퍼티를 검색하고, 없으면 그다음 __proto__를 검색한다. 따라서, 이과정에서 메서드 오버라이딩이 발생한다. 만약 __proto__ 의 메서드를 호출하고 싶다면, call을 통해 this를 인스턴스를 바라보도록 바꿔주면 된다.
프로토타입 체인
배열 리터럴에는 __proto__ 안에 또 __proto__가 있다.
prototype 객체가 객체이기 때문에 객체형태의 __proto__를 가진다. 기본적으로 모든 객체의 __proto__에는 Object.prototype이 연결된다.
Object.prototype은 언제나 프로토타입 체인의 최상단에 존재하게된다. 그러나, Object.is(), Object.kesy() 등 prototype에 정의되지않은 멤버들은 상속되지않아 Object() 생성자에 static하게 담겨있다.
출처 : 코어 자바스크립트 (정재남 저) , MDN