
JavaScript는 흔히 프로토타입 기반 언어(prototype-based language)라고 부른다.
여기서 프로토타입은 원형 객체를 의미한다.
클래스의 새로운 인스턴스가 만들어질 때 상속되는 속성과 메소드들은 각 인스턴스에 새롭게 만들어져 저장되는 것이 아닌 클래스의 prototype 속성 객체에 저장된다.
class Human {
constructor(name, age) {
this.name = name;
this.age = age;
}
sleep() {
console.log(`${this.name} is sleeping now...`);
}
}
먼저 Human 클래스를 만들었다. 이 클래스를 개발자 콘솔에서 console.dir() 로 확인해보자.

Human 클래스의 멤버 변수인 length 와 name 은 확인 가능하지만 sleep 메서드는 찾아볼 수 없다.
🎯 여기서 잠깐!
멤버 변수(혹은 데이터 멤버 / 클래스 필드)란?
클래스 내부의 캡슐화된 변수를 말한다. 쉽게 말해, 자바스크립트의 생성자 함수에서this에 추가한 속성(property)를 클래스 기반 객체지향 언어에서는 멤버 변수라고 부른다.
name 멤버 변수 바로 다음의 prototype 객체가 보이는가? 저것이 바로 프로토타입 객체이다.
조금 더 자세히 살펴보자.

prototype 객체 안에서 생성자 함수 constructor 와 sleep 메서드가 존재함을 확인 할 수 있다.
인스턴스(자식 객체)는 클래스(부모 객체)의 prototype 객체를 참조하여 속성과 메서드를 사용할 수 있다.
인스턴스를 하나 만들어보자.
const student = new Human('David', '21');
해당 인스턴스를 확인해보면 다음과 같이 나타난다.

멤버 변수인 age 와 name 은 보이지만 클래스에 존재하던 sleep 메서드는 보이지가 않는다.
위에서도 말했듯이 상속되는 속성과 메서드들은 인스턴스 객체 내부가 아닌 클래스의 prototype 에 저장된다.
[[Prototype]] 를 확인해보자.

클래스의 prototype 객체에 저장돼있는 constructor 와 sleep 을 확인할 수 있다.
객체는 자신의 프로토타입을 가리키는 [[Prototype]] 인터널 슬롯을 가지며 이것은 상속을 위해 사용된다.
함수 또한 객체이므로 [[Prototype]] 인터널 슬롯을 가진다. 하지만 함수 객체는 일반 객체와 다르게 prototype 속성도 가지고있다.
Function.prototype 을 가리킨다.__proto__ 속성으로 자식객체에서 부모객체의 [[Prototype]]에 접근할 수 있다.프로토타입 객체는 constructor 속성을 가진다. constructor 는 객체 입장에서 자신을 생성한 객체를 가리킨다.
function Person(name) {
this.name = name;
}
let foo = new Person('Carl');
// Person() 생성자 함수에 의해 생성된 객체(prototype)를 생성한 객체는 Person() 생성자 함수이다.
console.log(Person.prototype.constructor === Person);
// output : true
// foo 객체를 생성한 객체는 Person() 생성자 함수이다.
console.log(foo.constructor === Person);
// output : true
// Person() 생성자 함수를 생성한 객체는 Function() 생성자 함수이다.
console.log(Person.constructor === Function);
OOP의 4가지 특징 중 상속을 구현할때 프로토타입 체인을 사용한다.
자식 객체의 경우 부모 객체의 속성이나 메서드를 사용하고 싶을 때 프로토타입을 이용한다.
이 때 원하는 속성이나 메서드가 부모 클래스에서 찾을 수 없는 경우 [[Prototype]] 이 가르키는 링크를 타고 한
단계 더 올라가 검색을 시작한다. 이를 원하는 속성이나 메서드를 찾거나, [[Prototype]] 이 가르키는 링크가 없을때까지 수행한다.
이처럼 부모 - 자식 객체의 프로토타입 객체들이 연결되어있는 모습이 사슬과 같다하여 프로토타입 체인이라고 한다.
const newDiv = document.createElement('div');
newDiv.addEventListener('click', () => console.log('hi'));
newDiv 라는 변수에 div 태그를 저장하였다. 그 후 클릭 이벤트를 addEventListener 메서드를 통해
바인딩했다. 이 addEventListener 메서드는 어디에 존재할까?

[[Prototype]] 에 접근하기 위해 .__proto__ 속성을 사용하였다. 이를 통해 div 태그는 HTMLDivElement 인터페이스의 인스턴스인 것을 알 수 있었다. 하지만
프로토타입 객체에 addEventListener 메서드는 보이지 않는다. 더 상위로 올라가보자.

.__proto__ 속성을 통해 5번이나 링크를 타고 올라간 이후에야 EventTarget 객체의 프로토타입
객체에서 addEventListener 메서드를 발견할 수 있었다.
🎯 참고
PoeimaWeb - 프로토타입