※이 글을 이해하기 위해 자바스크립트와 객체지향, 그리고 자바스크립트 객체 생성 방법에 대한 지식이 필요합니다.
자바스크립트는 프로토타입 기반 객체지향 언어입니다. 프로토타입 기반 프로그래밍은 객체지향 프로그래밍의 한 종류로, 클래스 기반 언어에서 상속을 사용하는 것과 달리 객체의 원형(프로토타입)을 복제(Cloning)하여 객체를 확장합니다. 클래스리스(Class-less), 프로토타입 지향 혹은 인스턴스 기반 프로그래밍이라고도 부릅니다. 자바스크립트 외에도 Perl이나 R 등이 프로토타입 기반 언어에 속합니다.
자바스크립트의 새로운 버전인 ECMA2015에서 드디어 class 키워드를 도입하였습니다. 하지만 내부적으로는 여전히 프로토타입 기반으로 동작합니다.
프로토타입
프로토타입(prototype)이란, 단어 본래의 뜻(원형, 원본)에서 알 수 있듯이, 어떠한 객체가 만들어지기 위해 필요한 원형을 말합니다. 이러한 측면에서는 Java의 class와 프로토타입은 동일한 의미를 가집니다. 따라서 자바스크립트의 모든 객체는 자신을 생성한 객체 원형-프로토타입-에 대한 숨겨진 연결을 가집니다. 자바스크립트의 모든 객체는 Object 객체의 프로토타입을 기반으로 확장되기 때문에, 어떠한 객체든 연결의 끝에는 Object 객체의 프로토타입이 있습니다.
프로토타입에 대해 좀 더 쉽게 이해하기 위해서, 프로토타입의 생성이 어떻게 이루어지는지부터 살펴보겠습니다.
자바스크립트의 모든 객체는 함수(Function)로부터 시작됩니다.
function Foo() {}; //constructor function
var foo = new Foo();
위와 같이 객체를 생성하기도 하고, 객체 리터럴 방식을 이용하여 아래와 같이 객체를 생성하기도 합니다.
var bar = {}; //object literal
그러나 객체 리터럴 방식 역시 내부적으로 자바스크립트 엔진이 아래와 같이 인터프리트 하게 됩니다.
var bar = new Object();
여기서 Object라는 최상위 함수의 생성자를 통해서 객체를 생성하게 되고, 이는 Array든 Function이든 Date, RegExp 등 모두 동일합니다. 즉, 자바스크립트에서 프리미티브 타입을 제외하고는 모두 함수입니다.
함수를 생성하게 되면, 총 2개의 객체가 생성됩니다.
단순히 생성되기만 하는 것이 아니라, 이 둘은 서로 이어져 있습니다. 함수에서는 프로토타입 객체에 prototype이라는 내부 변수로 하여금 접근할 수 있고, 프로토타입에서는 constructor라는 변수로 함수에 접근이 가능합니다. 물론 실제로는 위보다 조금 더 복잡하게 구조가 이루어져 있습니다.
그리고 이 객체로 하여금 인스턴스를 생성하게 되면, 아래와 같은 연결이 이루어집니다.
유의해야 할 점은, 위에서 언급했듯이 자바스크립트의 객체는 프로토타입 클로닝, 즉, 복제를 통해서 확장한다는 점입니다.
Foo 예제에 아래와 같이 코드를 첨가하겠습니다.
Foo.prototype.x = 1
Foo.prototype.y = 2
Foo.prototype.print = function() { console.log("hello") }
※prototype object에 변수를 추가하는 것은 권장되지 않습니다. 이는 Java에서 클래스에 추상 필드가 추가되는 것과 동일하기 때문에 반드시 필요한 경우에만 사용하여야 합니다.
그리고 Foo의 프로토타입 객체와 foo 인스턴스 정보를 확인해보겠습니다.
foo 인스턴스에서 Foo 프로토타입의 x 변숫값에 접근이 가능하지만, 인스턴스를 통해 x값을 변경하게 되면 프로토타입 객체의 변수 값이 바뀌는 것이 아니라 복제된 x가 foo 인스턴스에 생성되고 값이 할당되는 것을 볼 수 있습니다. 만약 prototype의 x를 바꾸고 싶다고 한다면, foo._proto_. x의 값을 바꾸어주어야 하는데, 이 _proto_가 무엇인가에 대해서는 아래에서 다루도록 하겠습니다.
prototype link & prototype object
대부분의 개발자들이 자바스크립트의 프로토타입을 이 prototype property라고 생각합니다. 그러나 실제로 프로토타입은 Prototype Link와 Prototype Object를 통틀어 지칭하는 말입니다.
(1) Prototype Object
이 프로퍼티는 객체를 위한 함수가 생성될 때 생성됩니다. Prototype Object는 일반적인 객체이기 때문에 속성을 마음대로 추가/삭제할 수 있습니다. 우리가 자바스크립트에서 객체를 생성하여 사용할 때, 프로토타입 프로퍼티에 메서드를 정의하여 사용했던 것은 모두 이러한 특성 덕분입니다.
(2) Prototype Link
위의 예제 코드에서 인스턴스를 생성했을 때, 생성자 인스턴스가 _proto_라는 속성을 통해 Foo Function을 참조하고 있는 것을 볼 수 있습니다. 이 _proto_가 바로 Prototype Link입니다. 실제로 객체 인스턴스가 생성될 때 생성되며 모든 객체는 이 _proto_ 속성을 가지고 있으며, 생성될 때 부모 함수인 Prototype Object를 가리키게 됩니다.
객체 자체를 참조하고 있기 때문에, _proto_를 통해 접근하게 되면 프로토타입의 값을 바꿀 수 있게 되는 것입니다. 이렇듯 _proto_ property를 통해서 상위의 프로토타입과 연결되어 있는 형태를 프로토타입 체인(Chain)이라고 합니다. 프로토타입 체인을 이용하면 객체의 상속을 구현할 수 있습니다.
prototype link는 프로토타입 체인과도 밀접하게 연결되어 있는 개념으로, 일단 여기까지 이해했다면, 우리는 프로토타입에서 가장 중요한 프로토타입 체인을 이해할 준비가 모두 끝났습니다. 그러므로 다음 글에서 prototype link와 프로토타입 체인에 대해 더 자세히 다루어 보도록 하겠습니다.
references
'Javascript' 카테고리의 다른 글
ECMAScript 2020 aka ES11 (0) | 2020.11.15 |
---|---|
Prototype Chain (0) | 2020.11.15 |
[Javascript] Debounce & Throttle (0) | 2020.10.21 |
[Javascript] 자바스크립트에서 메모리 누수의 4가지 형태 (0) | 2020.10.21 |
[Javascript] Closure (0) | 2020.10.21 |
댓글