자바스크립트는 프로토타입 기반 객체 지향 언어라고 불린다. 모든 객체들은, 속성과 메서드를 상속받기위한 템플릿(그러니깐 일종의 틀)로 프로토타입 객체를 가진다는 의미이다. 정확히 말하자면 상속되는 속성과 메소드들은 각 객체가 아니라 객체의 생성자의 prototype이라는 속성에 정의되어 있다. 이 어려운 말이 도대체 무슨 말일까?
클래스와 인스턴스는 부모와 자식의 관계와 비슷하다. 부모가 가진 속성을 자식이 쓸 수 있도록 물려준다.
class Human {
constructor (greet) {
this.hi = 'hello!'
}
}
const minsu = new Human('minsu');
console.log(minsu.hi) // 'hello!'
이처럼 Human에 있는 속성을 minsu가 물려받는다.
그런데 이 방법 말고도 자식에게 물려줄 수 있는 방법이 하나 더 있는데, 그것이 바로 prototype이다. 다시말하자면, protoptype은 부모의 유전자라고도 말할 수 있다. 그런데 prototype 역시 객체이다. 그렇다면 prototype에 속성을 추가할 수도 있다는 말이다.
Human.prototype.bye = 'bye!'
console.log(minsu.bye); //'bye!'
minsu에는 추가된 적 없지만, minsu 역시 bye라는 프로퍼티를 읽을 수 있다. minsu의 부모라 할 수 있는 Human의 유전자에 bye를 추가했기 때문이다.
자바스크립트에서 어떠한 프로퍼티를 사용하고 싶다면 객체.프로퍼티 키 의 방식을 사용한다. 그런데 만약 해당 객체에 해당 프로퍼티 키가 없다면? 자바스크립트는 여기서 멈추지 않고 부모(정확히는 부모의 유전자)를 뒤져서 해당 프로퍼티 키가 있는지 없는지 찾는 것이다.
proto는 prototype에 접근할 수 있는 방법이나 권장되지 않는다. 이는 Object.setPrototypeOf와 Object.getPrototypeOf로 대체해서 사용할 수 있다.
const ronaldo = {goal : 'siu!'};
ronaldo.__proto__ = minsu ;
console.log(ronaldo.hi); //hello!
console.log(ronaldo.bye); // bye!
이처럼 ronaldo의 프로토타입으로 minsu를 설정해주니 minsu의 프로퍼티는 물론 민수의 부모의 부모의 프로퍼티인 bye 까지 쓸 수 있게 되었다.
한가지 생각해보면, 모든 배열은 Array의 인스턴스이다. Array의 프로토타입에는 수많은 메서드들이 이미 정의되어 있다. 따라서 우리가 배열에 메서드를 사용하는 것은, 사실 배열의 부모인 Array 에게서 사용하는 것이다. 즉, 부모의 유전자로부터 사용하는 것이라고 말할 수 있다.