자바스크립트를 공부하다보면, 특히 array의 메소드를 검색할 때 prototype
이라는게 곳곳에 붙어있는 것을 확인할 수 있다. 중요한 개념이라는 것은 분명히 알겠는데 프로토타입이라는게 도대체 뭘까?
다른 프로그래밍 언어들과 달리 자바스크립트에는 class라는 것이 없다. (ES6에 class라는 문법이 추가되었지만) 우리가 자바스크립트를 표현할 때는 '클래스(class) 기반의 언어'가 아닌 '프로토타입(prototype) 기반의 언어'라는 표현을 한다. 왜 그럴까? 우리가 객체를 하나 생성할 때 그 객체는 자동적으로 프로토타입을 가진다. 다시말해 자바스크립트의 모든 객체는 '프로토타입'이라는 다른 객체에 연결되고(be linked to prototype) 객체는 그 프로토타입에 있는 property와 method를 참조할 수 있다.
위의 그림에서 살펴보면 user1이라는 object에는 state라는 속성이 없다. user1.state라는 명령을 실행하면 자바스크립트는 user1 object를 살펴보고 state라는 속성이 없으므로 프로토타입 객체를 확인한다. 만약 그 객체에도 해당 속성이 없다면 다른 프로토타입을 확인한다. 이 과정들을 prototype chain이라고 한다.
class 개념이 없는 자바스크립트에서는 객체지향의 대표적인 컨셉 중 하나인 '상속'이 이루어질 수 없지만 이처럼 prototype을 이용해서 연결할 수 있다.
__proto__
💁프로토타입에 대해 추상적으로 정리를 했지만 잘 와닿지 않아 실제 예시를 보며 다시 한번 정리해보자.
var obj = {}
obj.toString(); //[object Object]
obj라는 새로만든 객체에 우리는 toString 이라는 메소드를 정의한 적이 없지만 obj.toString()을 실행하면 어떤 결과값이 나온다. 왜그럴까?? 이는 toString이 자바스크립트에 이미 내장되어 있는 가장 상위의 프로토타입인 Prototype Object
에 정의되어 있는 속성이기 때문이다. obj.toString()이라는 명령을 실행했을 때 자바스크립트는 obj에 toString이라는 속성이 있는지 확인하고 없으면 그 다음 프로토타입인 prototype object를 확인한 것이다.
obj의 뚜껑을 열어보면 우리가 정의한 적도 없는 __proto__
라는 프로토타입에 이미 연결되어 있는 것을 확인할 수 있다.
function Person() {}
Person.prototype.eyes = 2;
Person.prototype.nose = 1;
var kim = new Person();
var park = new Person();
](
console.log(kim.eye); // 2
위의 코드에서 Person이라는 빈 함수로 생성된 kim이라는 객체가 eyes라는 갖고 있지도 않은 속성을 실행할 수 있는 이유는
(1) prototype이란 것을 이용하여 Person.prototype이라는 eyes라는 속성을 가진 객체를 만들어줬고
(2) kim.eye를 실행했을 때는 Person 함수를 확인하고 eyes라는 속성이 정의되어 있지 않기 때문에
(3) Person.prototype을 확인하게 되기 때문이다.
kim을 열어보면 Person의 프로토타입에 정의해 준 속성이 __proto__
라는 것으로 이어져 그 안에 들어있는 것을 볼 수 있다.
마지막으로 다시! 정리해서 kim 객체에는 eyes가 없어서 eyes를 찾을 때 까지 상위 프로토타입을 탐색한다. 최상위에 있는 Prototype Object까지 탐색했는데도 없으면 undefined가 리턴되는 것이다.
프로토타입 체인은 다시 말해 __proto__
속성을 통해 상위 프로토타입과 연결되어 있는 형태를 일컫는다고 이해하면 된다.
참고
Youtube | Javascript question: What is a Prototype
Medium | [Javascript ] 프로토타입 이해하기