prototype

프로토타입은 Javascript 객체가 서로 기능을 상속하는 매커니즘이다(MDN).

프로토 타입이란 클래스나 객체의 내용 복사 없이도 상속의 효과를 구현할 수 있게 해주는 방법이다.

  • 프로토타입은 직접 참조 당하지 않고 프로토타입 링크(__proto__)를 통해 부모의 프로토타입 링크만 참조한다.

  • 프로토 타입 속성(property's)의 값은 객체이며, 프로토타입 체인 아래에 있는 객체에 상속되기를 원하는 속성과 메서드를 저장하기 위한 공간인 객체이다.

  • 그래서 Object.is(), Object.keys()같은 메서드들은 프로토타입 객체 안에 정의되지 않았기 때문에 Object.prototype에서 상속되는 객체 인스턴스나 객체 유형(object type)에 의해 상속되지 않는다.

  • 프로토타입 객체에는 속성과 메서드를 추가할 수 있으며, 원하는 객체로 완전히 교체할 수도 있다.

  • 함수를 생성자로 사용하여 new 키워드와 함께 객체를 생성할 때, 객체는 생성자의 프로토타입을 가리키는 프로토타입 링크를 얻고 프로토타입 속성에 접근할 수 있다.

  • 객체 고유의 속성은 이름이 같은 프로토타입 속성보다 우선한다.

  • hasOwnProperty() 메서드를 통해 객체의 고유한 속성과 prototype 속성을 구분할 수 있다.

프로토타입 링크(__proto__)

프로토타입 링크를 __proto__라고 편의상 적어놓긴 했지만 정식 명칭은 [[prototype]]이고, __proto__은 크롬을 포함한 최신 자바스크립트 환경에서 사용하는 이름이다.

그런데 프로토타입 링크를 언제 사용되는걸까?

현재 객체에 존재하지 않는 속성에 접근하려고 할때 프로토타입 링크를 통해 프로토타입 링크가 참조하고 있는 부모 객체를 찾으려고 할때 사용된다.

예를 들어 아래와 같이 배열을 하나 정의했다고 하자.

const arr = [1, 2, 3];

arrprototype을 확인해 보면 undefined이고 위 코드에서 확인할 수 있다시피 따로 프로토타입에 만들어 놓은 메서드는 없다. 하지만 map이나 filter등 내가 정의하지 않는 메서드를 사용할 수 있는데, 이 이유가 프로토타입 링크에 의한 탐색 때문인 것이다.

그리고 프로토타입 링크는 생략이 가능하고, 우리가 평소에 사용했듯이 생략을 하고 사용해야 한다.

const arr = [1, 2, 3];
arr.__proto__.map((v) => console.log(v));

만약 위 코드와 같이 프로토타입 링크를 생략하지 않고 사용하면 자바스크립트의 this가 점(.) 앞에 객체를 바라보도록 설계되었기 때문에 this바인딩 문제가 발생한다.

프로토타입 체이닝

프로토타입 링크(__proto__)를 따라 탐색하는 것을 말한다.

객체의 프로퍼티나 메서드를 사용할때, 해당 객체에 프로퍼티가 존재하지 않는다면 현재 객체의 __proto__ 프로퍼티가 있는 체크하고 없다면 부모의 __proto__ 객체를 탐색하며, 최종 Objects.prototype 객체까지 없으면 undefined를 반환한다.

화살표 함수와 일반 함수에서의 프로토타입

함수 선언문의 함수(function)은 프로토타입을 가지고 있으며, constructor는 자기 자신이고 __proto__ 속성으로 Object를 상속 받고 있다.

  • 화살표 함수는 프로토타입 속성을 가지고 있지 않으며, 따라서 생성자 함수로도 사용할 수 없다.

Last updated