클래스의 인스턴스에서 사용할 수 있는 메서드 = 프로토타입(Prototype) 메서드
class Car {
constructor(make, model) {
this.make = make;
this.model = model;
this.userGears = ["P", "N", "R", "D"];
this.userGear = this.userGears[0];
}
shift(gear) { // 메서드 함수
if(this.userGears.indexOf(gear) < 0)
throw new Error(`Invaild gear: ${gear}`);
this.userGear = gear;
}
}
상기의 코드에서 작성된 shift(gear)부분은 class의 메서드 이다. 이 shift도 프로토타입 메서드이다. 보통 프로토타입 메서드는 Car.prototype.shift
로 표기할 때가 많다. 최근에는 프로토타입 메서드를 #으로 표시하는 표기법이 많다고 한다. car.prototype.shift
= Car#shift
new
키워드로 새 인스턴스를 만들었을 때, new
키워드로 만든 새 객체는 생성자의 prototype 프로퍼티
에 접근할 수 있다. 객체 인스턴스는 생성자의 prototype 프로퍼티
를 __proto__
프로퍼티에 저장한다.
__proto__ 프로퍼티
는 자바스크립트의 내부 동작 방식에 영향을 미친다. 밑줄 두 개로 둘러싼 프로퍼티는 모두 그렇다. 이런 프로퍼티를 수정하는 것은 정말로 위험한 행동이다.
Class
와 Instance
는 Prototype
를 공유한다.
예를 들어, Class
를 정의 할 때 같이 정의한 메서드
는 Prototype
에 들어간다. 그리고 Class
를 이용한 객체 인스턴스
를 생성하면 이 인스턴스
는 Class
와 같은 프로토타입
을 공유한다. 만약에 이 객체 인스턴스에서는 존재하지 않는 메서드는 실행한다고 하면, JavaScript는 일단 인스턴스 내부에서 메서드는 찾는다. 하지만, 이 메서드가 인스턴스내에 존재 하지 않는다면 프로토타입으로 이동하여 실행시킨 메서드를 찾는다. 해당 메서드가 프로토타입에 존재할 시, 해당 메서드를 실행시키고 인스턴스에 추가한다. 한번 더 같은 메서드를 실행시키면 프로토타입이 아닌 인스턴스내에서 메서드를 찾아서 실행시킨다.
그림으로 표현하면 이런식이다.
글로만 설명하면 프로토타입이란 개념이 매우 어렵다고 느끼지만, 그림으로 차분히 따라오면 프로토타입이란 어떤 개념인가 알기 쉽다고 생각한다.