JavaScript Prototype

JavaScript의 prototype를 처음부터 다시 공부하면서 적어보았다. C/C++와 Java로 프로그래밍을 시작했고 오래써왔기 때문에 prototype을 이해하는데 꽤 오랜시간이 걸렸다. 둘 다 상속, 캡슐화, 추상화, 다형성 등을 전부 지원하지만 접근하는 방식은 좀 다를 뿐 깊게 들어가보면 동작하는 방식은 대동소이하다. Java와 비교하면서 적었기 때문에 Java를 쓰시는 분이면 이해하기 쉬울 듯하다.

Java Class와 JavaScript Prototype

Java Class

Java는 class를 설계도삼아 object를 만들어낸다. 위의 코드에서는 Point class instance인 p1, p2가 생성된다. 메모리 관점에서 봤을 때 완전히 똑같은 object 두 개가 따로 메모리 상에 저장된다.

JavaScript Prototype

JavaScript 코드는 Java 코드와 비교하면서 한 줄 한 줄 설명해 해보았다.

Line 2 ~ 5

Java에서 class키워드를 사용해서 class를 선언하는데 비해서, JavaScript에서는 먼저 생성자(constructor)를 만든다. Point function이 선언됨과 동시에 Point function object가 생성된다 – JavaScript에서는 function도 object로 관리된다. Point function object의 내부에는 prototype이라는 property가 자동적으로 생성된다. 이게 바로 Point의 prototype이다. prototype은 메모리 상에 존재하는 object이며 거기서 생성/파생되는 모든 object의 원형이 된다. 기본으로 만들어 지는 prototype은 아무런 값이 없는 object이다 – 보든 JavaScript의 Object가 그렇듯 prototype object도 Object.prototype을 기반으로 한 object이다.

생성자Point function 에서는 일반적으로 property를 만들고 초기화하는 일을 한다. Java에서는 x, y field1 를 class 내에 따로 선언하지만 JavaScript는 따로 property1 선언은 하지 않고 생성자 내에서 this.x = x처럼 값을 넣어서 선언 및 초기화 한다. 생성자에서 추가 된 property는 prototype과는 상관없이 각 object에 종속된다.

Line 8 ~ 10

print method를 Point의 prototype에 추가한다. 이것은 Java의 print method와 같은 역할을 하게 된다. prototype에 추가 된 method와 property는 이후에 생성된 모든 instance에서 접근이 가능하다.

Line 14 ~ 15

Line 14-15에서는 new키워드로 Point instance p1, p2를 생성한다. 내부적으로 동작하는 걸 자세히 따져보면 C/C++나 Java같은 instance화 라기보다는 prototype을 가리키는 빈 object를 만드는 것에 가깝다.

p1p2는 아주 단순한 구조를 가지고 있다. 빈 object에 x, y property를 가지고 있고, 거기에 추가로 숨겨진 property인 [[Prototype]]를 가진다 – Chrome, Safari 등 많은 모던브라우저에서는 __proto__라는 이름을 사용하고 있지만 ECMAScript 표준은 [[Prototype]]이다.

두 instance의 [[Prototype]]은 모두 Person.prototype를 가리킨다. 간단히 말해, p1p2는 하나의 prototype object를 공유한다. 이렇게 prototype object를 공유함으로써 Prototype Chain과 Property Shadowing이 가능해진다.

JavaScript prototypePoint.prototypep1p2x:0, y:0x:5, y:5print function

[1]: Java에서는 field, JavaScript에서는 property