자바스크립트 클래스는 절대 특별한 것이 아니고 그냥 기존에 존재하던 프로토타입 기반의 상속과 생성자 함수의 문법적인 포장지입니다. JS 클래스 뒤에 숨은 아이디어를 이해하기 위해서, 우리는 생성자 함수와 프로토타입 그리고 다른 연관된 개념들을 이해할 필요가 있습니다.
자바스크립트는 모든 것이 함수인 함수형 언어이기 때문에 자바스크립트내의 기능에서 클래스를 가지기 위해서는 생성자 함수가 사용됩니다. 생성자 함수가 어떻게 이용되는지 확인해봅시다.
function Vehicle(make, model, color) {
this.make = make,
this.model = model,
this.color = color,
this.getName = function () {
return this.make + " " + this.model;
}
}
위의 함수는 자바스크립트 클래스의 생성자와 거의 흡사한 기능을 제공합니다. Vehicle
타입의 오브젝트를 제공하기 위해서, 우리는 다음과 같은 코드를 작성합니다.
let car = new Vehicle("Toyota", "Corolla", "Black");
let car2 = new Vehicle("Honda", "Civic", "White");
완벽합니다. 이제 코드 한 줄이면 Vehicle
타입의 오브젝트를 우리가 원하는 만큼 만들 수 있습니다.
하지만 기다려보세요. 이 기술에는 몇가지 문제점이 있습니다.
우리가 new Vehicle()
이라는 코드를 작성할 때, 자바스크립트 엔진이 실제로 하는 일은 우리의 각 오브젝트에 대해서 Vehicle
생성자 함수를 복사하는 일입니다. 각각 그리고 모든 프로퍼티 그리고 메소드가 Vehicle
의 새로운 인스턴스에 복사됩니다. 그래서 이게 무슨 문제가 있냐고요?
문제는 바로 우리는 우리 생성자 함수의 멤버 함수가 모든 오브젝트에서 반복되는 것을 원하지 않는다는 것이죠. 이건 중복된 코드를 계속 생성하는 것입니다. 또 다른 문제는 우리가 새로운 프로퍼티나 메소드를 존재하는 생성자 함수(constructor function)에 추가할 수 없다는 것입니다. 다음과 같이요.
car2.year = "2012"
// (역자 주: 댓글에 이 부분을 지적하는 사람이 있었습니다.
// '멀쩡하게 동작하는데 왜 동작이 안된다고 했느냐, 무슨 의미냐'라는 식으로 물었고
// 저자는 '존재하는 오브젝트에는 가능하지만 생성자 함수에는 추가할 수 없다'라고 하였습니다.)
year 프로퍼티를 추가하려면 생성자 함수 자체에 추가해야 할 것입니다.
function Vehicle(make, model, color, year) {
this.make = make,
this.model = model,
this.color = color,
this.year = year,
this.getName = function () {
return this.make + " " + this.model;
}
}
자바스크립트에서 새로운 함수가 만들어질때마다, 자바스크립트 엔진은 기본으로 prototype
프로퍼티를 추가합니다. 이 프로토타입은 우리가 "프로토타입 오브젝트(prototype object)"라고 부르는 것입니다. 기본으로 이 프로토타입 오브젝트는 우리 함수를 다시 가리키는 생성자 프로퍼티와 오브젝트인 또 다른 프로퍼티 __proto__
를 갖고 있습니다. 다음 내용을 봅시다.
__proto__
프로퍼티는 'dunder proto'라고 불립니다. 그리고 이 프로퍼티는 우리의 생성자 함수의 프로퍼티를 가리킵니다.
'dunder'라는 말은 파이썬에서 왔습니다. 변수 양 끝이 __ 로 묶여 있는 변수를 'dunder' 프로퍼티라고 합니다.