[자바스크립트] 프로토타입

자바스크립트는 프로토타입 기반 언어이다. 또한 객체지향 언어이기도 하다. 그러나 자바스크립트는 클래스 기념이 없다. 대신에 프로토타입(Prototype)이 존재한다.

클래스 개념이 없으니 기본적으로 상속기능도 없으며 보통 프로토타입을 기반으로 상속을 흉내내어 사용한다.
javascript는 프로토타입을 이용한 클로닝(Cloning)과 객체특성을 확장해 나가는 방식을 통해 새로운 객체를 생성하게 된다.
(참고로 ESMA6 표준에서는 Class 문법이 추가되었다. 하지만 문법이 추가 된 것이지 클래스 기반으로 바뀐 것이 아니다. 여전히 Prototype기반이다)

자바스크립트의 프로토타입(Prototype)이란?

자바스크립트에서는 Prototype LinkPrototype Object 가 존재한다. 그리고 이 둘을 통틀어 Prototype이라 부른다.

Prototype Link : 객체가 생성될 때 조상이었던 함수의 Prototype Object를 가리키며 객체안에서 proto 가 바로 그것이다.

Prototype Object : 자기 자신의 분신 이며 자신을 원형으로 만들어질 다른 객체가 참조할 프로토타입이 된다. 즉 객체 자신을 이용할 다른 객체들이 프로토타입으로 사용할 객체가 Prototype Object 가 되는 것이다.

아래 예제를 살펴보자

예제1 코드
  • js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var A = function () { };
A.x=function() {
console.log('hello');
};
A.prototype.x = function () {
console.log('world');
};
var B = new A();
var C = new A();

B.x();
> world
C.x();
> world

B, C를 생성하기 위한 객체 원형 프로토타입은 A이다. 하지만 여기서 반드시 집고 넘어가야 하는 사실은 B,C는 A를 프로토타입으로 사용하기 위해 A의 Prototype Object를 사용한다는 것이다.
그리고 이 Prototype Object는 A가 생성될 당시의 정보 var A = function () { };는 비어있는 객체상태이기 때문에 A.x가 적용되지 않아 ‘hello’가 출력되지 않는다.
그러나 A.prototype.x를 통해 접근하게 되면 B,C 모두 A의 Prototype Object 를 참조하기 때문에 위의 결과에서 ‘world’ 가 출력되는 것이다.

위 예제를 상속모델 그림으로 표현하면 다음과 같다.

상속모델 표현도상속모델 표현도

그림과 코드를 함께 보도록 하자.
코드의 첫 번째 줄에서 A Object가 생성되면서 A에 대한 Prototype Object가 생성된다.(자기 자신의 분신이 생성된다)
그림에선 가운데의 A 객체가 생성되고 그 아래 A에 대한 Prototype Object가 만들어지며 A 객체는 A Prototype Object를 가리킨다.
또한 A Prototype Object안의 Constructor를 보면 A 객체를 가리키고 있다. 즉 자신의 원형이 A객체라는 뜻이다.

2~4라인에서 A 객체의 속성 x에 함수를 대입하였다. 그림에서도 A 객체에 x속성이 추가된 것을 확인 할 수 있다.

5~7라인에서 A Prototype Object에 직접적으로 접근하여 함수를 할당하였다. 그림에서도 A Prototype Object 에 x속성이 존재하는 것을 확인 할 수 있다.

8~9라인에서는 A 객체를 기반으로 B, C객체를 만들었다. 자바스크립트는 프로토타입 기반이기 때문에 A 객체가 아니라 A Prototype Object를 참조하여 B, C 객체가 만들어지게 되는 것이다. 즉 그림에서 처럼 B, C객체는 A Prototype Object를 링크하게 된다.

이후 10, 12라인에서 B.x()와 C.x()를 호출하게되면 A객체의 x속성이 아니라 프로토타입기반으로 B,C가 생성되었으므로 A Prototype Object 의 x가 공유되어 ‘hello’가 아닌 ‘world’가 출력된다.

자바스크립트의 프로토타입 체인(Prototype Chain)

프로토타입 체인이란 프로토타입을 상속해서 만들어지는 객체들간의 연관관계를 의미 한다. 위쪽 설명에서 protoPrototype Link를 의미하며 이를 따라 올라가보면 Object 객체의 Prototype Object에 다다른다.
그렇기 때문에 자바스크립트의 모든 객체는 Object객체로부터 파생된 자식들이며 기본적인 Object Prototype의 내장함수들이 자식들에게도 공유되는 것이다.(toString, hasOwnProperty등)

이러한 프로토타입 체인은 하위 객체에서 상위 객체의 프로퍼티와 메소드를 상속받는다. 사실 상속이 아니라 공유하고 있는 것이다.

아래의 예제와 표현도를 살펴보자

예제2 코드
  • js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var A = function () { };
A.prototype.x = function () {
console.log('hello');
};
var B = new A();
var C = new A();

B.x();
> hello

C.x();
> hello

A.prototype.x = function () {
console.log('world');
};

B.x();
> world

C.x();
> world
상속모델 표현도상속모델 표현도

위쪽에서 살펴보았던 예제와 비슷하다. 객체 A를 만들고 A의 Prototype Object에 x 속성을 추가하였다. 이후 B, C객체는 A의 Prototype Object를 참조하였다.
5~12라인에서 B,C 객체를 만들고 x속성을 호출하게 된다. 그러나 B,C객체에는 x속성이 없다.
따라서 프로토 타입 체이닝에 의해 상위 객체의 속성을 찾게 되며 즉,
A의 Prototype Object에 있는 x을 찾아 ‘hello’가 출력된다.
이러한 방법으로 만약 찾으려는 x가 없는 경우 계속해서 상위객체를 찾는다.
상위객체를 참조하여도 해당 속성이 없다면 마지막에는 Object의 Prototype 객체까지 올라가게 된다.
그래도 없다면 undefiend를 리턴하게 된다.


이번 공부 내용을 통해 그동안 뜬구름만 잡았던 프로토타입에 대해 깊숙하게 이해 할 수 있었다.

참조링크

Javascript 프로토타입 이해하기 – 오승환 – Medium
Javascript 기초 - Object prototype 이해하기 | Insanehong’s Incorrect Note