클래스 기반 객체지향 프로그래밍 언어는 객체 생성 이전에 클래스를 정의하고 이를 통해 객체(인스턴스)를 생성한다. 하지만 프로토타입 기반 객체지향 프로그래밍 언어는 클래스 없이(Class-less)도 (ECMAScript 6에서 클래스가 추가되었다) 객체를 생성할 수 있다. 자바스크립트가 바로 그러하다.
자바스크립트의 모든 객체는 자신의 부모 역할을 담당하는 객체와 연결되어 있다. 그리고 이것은 마치 객체 지향의 상속 개념과 같이 부모 객체의 프로퍼티 또는 메소드를 상속받아 사용할 수 있게 한다. 이러한 부모 객체를 프로토타입 객체 또는 줄여서 프로토타입이라 한다.
자바스크립트에서 human이라는 객체를 만들면, human.prototype이라는 prototype객체가 함께 만들어진다.
function Human(name) {
this.name = name;
}
Human.prototype.walk = function () {...}
let steve = new Human(name);
예를 들어 Human
이라는 생성자 함수가 있고, new
키워드를 이용해 Human
을 호출하고 steve
라는 인스턴스를 만들었다. 그리고 Human.prototype
에 walk
라는 메서드를 추가했다.
코드를 살펴보면, Human
생성자 함수가 아니라, 생성자 함수의 속성인 Human.prototype
객체에 메서드를 추가한 것을 볼 수 있다.
이는, prototype 객체가 바로 원형(original form)이며, 생성자 함수의 속성과 메서드가 정의되어 있기 때문이다. 생성자 함수에 정의되어 있는 것이 아니다. 생성자 함수가 가지고 있는 prototype 객체에 해당 객체의 속성과 메서드가 정의되어 있는 것이다.
따라서 우리가 커스텀한 메서드(walk)를 추가할 때도 생성자 함수가 아니라, 생성자 함수의 속성과 메서드가 정의되어 있는 prototype 객체에 추가해야 하는 것이다.
Human
이라는 함수를 만들면, 자바스크립트는 Human.prototype
객체를 만들어 Human
함수에 속성으로 넣어준다..prototype
을 붙여 prototype 객체에 접근할 수 있다. 반대로 prototype 객체에서는 .constructor
를 붙여 생성자에 접근할 수 있다.new
키워드를 이용해 클래스로부터 인스턴스를 만든다. 정확히는, new
키워드를 사용하면, prototype 객체를 통해 인스턴스화(instantiation)된 객체를 반환한다.steve
는 **.__proto__**
를 통해서 자신이 상속받은 클래스 Human
의 Human.prototype
객체에 접근할 수 있다.모든 객체는 자신이 상속받은 부모 객체의 prototype 객체에 .proto를 통해 접근할 수 있다.
.proto를 실행하면 자신의 조상 객체들의 prototype 객체들을 확인할 수 있다.
steve.__proto__ === Human.prototype // true
Human.__proto__ === Fucntion.prototype // true
steve.__proto__.__proto__ === Function.prototype // true