JS는 기본적으로 객체지향으로 만들어진 언어가 아니다. 따라서 ec6이전에는 class조차 없었으며 class가 없으니 상속기능도 없었다. 그래서 보통 프로토타입(prototype)을 기반으로 상속을 흉내내도록 구현했었다.
function ice_cream(){
this.temp = 'cold'
this.sweet = true
}
let world_con = new ice_cream();
let nugabar = new ice_cream();
위의 방식대로 사용하게 된다면 메모리에는 temp와 sweet이 총 두개씩 4개가 할당이 된다. 아이스크림의 종류가 늘어날 수록 할당되는 메모리의 양도 기하급수적으로 늘어난다. 이를 프로토타입으로 해결할 수 있다.
function ice_cream(){}
ice_cream.prototype.temp = 'cold'
ice_cream.prototype.sweet = true
let world_con = new ice_cream();
let nugabar = new ice_cream();
위를 보면 ice_cream.prototype이라는 빈 객체가 어디엔가 존재하며 ice_cream 함수로부터 생성된 객체들은 이 어딘가 존재하는 prototype object를 가져다 사용(상속)할수 있다.
프로토타입은 프로로타입 링크(prototype link)와 프로토타입 오브젝트(prototype object)가 있으며, 이둘을 통틀어 프로토타입이라고 부른다.
객체는 언제나함수로 생성된다. 아래의 객체를 만드는 과정은 모두 동일하다.
function make_obj(){...}
let obj = new make_obj()
///
let obj = {}
///
let obj = new Object()
Object()또한 자바스크립트에서 기본적으로 제공하는 객체를 만드는 함수이다. 함수가 정의될때에는 두가지 일이 발생한다.
해당 함수에 생성자(constructor)부여
생성자가 부여된다면 new를 통해 객체를 만들어 낼 수 있게된다.
해당함수의 prototype object 생성 및 연결
함수가 정의될때 함수 뿐 아니라 prototype object또한 같이 생성된다. 그리고 생성된 함수는 prototype이라는 속성을 통해 prototype object에 접근할 수 있다. prototype object는 기본적인 속성으로 constructor와 __proto__를 가지고 있다.
constructor는 prototype object와 같이 생성되었던 함수를 가리킨다.
__proto__는 prototype link이다.
function ice_cream(){}
ice_cream.prototype.temp = 'cold'
ice_cream.prototype.sweet = true
let world_con = new ice_cream();
let nugabar = new ice_cream();
wolrd_con.temp // 'cold'
위의 예제에서 world_con에는 temp라는 속성이 없는데 어떻게 참조가 가능할까. 그것은 __proto__가 존재하기 때문이다. prototype속성은 함수만 가지고 있었던 것에 반해 __proto__는 모든 객체가 가지고 있는 속성이다.
__proto__는 객체가 생성되었을 때에 조상이었던 함수의 prototype object를 가리킨다. wolrd_con은 ice_cream으로부터 생성되었으니 world_con.__proto__는 ice_cream.prototype과 같다.
이렇게 __proto__속성을 통해 상위 프로토타입과 연결되있는 것을 prototype link라고 한다. 이러한 프로토타입의 체인구조 때문에 모든 객체는 Object의 자식이며, Object.prototype을 사용할 수 있다.
function ice_cream(name){
this.is_cold = true
this.sweet = true
}
ice_cream.prototype.melt_down = function(){
this.is_cold = false
console.log('no!!')
}
아이스크림 생성자를 만들어 보았다. 차가운지(is_cold),달콤한지(sweet) 그리고 녹았을때의 메소드만을 정해놓았다. 그리고 돼지바의 생성자 또한 만들어 보겠다.
function pig_bar(name){
this.crispy = true
}
바삭한지(cirspy)의 여부만을 추가하고 나머지 속성 및 메소드는 ice_cream의 것을 가져올것이다.
프로토타입의 상속은 다음과 같은 단계로 진행된다.
function pig_bar(name){
this.crispy = true
}
pig_bar.prototype = Object.create(ice_cream.prototype)
function pig_bar(name){
this.crispy = true
}
pig_bar.prototype = Object.create(ice_cream.prototype)
pig_bar.prototype.constructor = pig_bar
function pig_bar(name){
ice_cream.call(this,name)
this.crispy = true
}
pig_bar.prototype = Object.create(ice_cream.prototype)
pig_bar.prototype.constructor = pig_bar
자바스크립트 ES2015부터는 이런 프로토 타입의 생성과정을 더욱 쉽게 하기 위해 클래스가 도입되었다. 아래의 예제는 위의 돼지바만들기와 동일하다.
class ice_cream{
constructor(name){
this.is_cold = true
this.sweet = true
}
melt_down(){
this.is_cold = false
console.log('no!!')
}
}
class pig_bar extends ice_cream {
constructor(name){
super(name)
this.crispy = true
}
}
ice_cream클래스의 constructor 객체는 객체의 속성을 정의하는 곳이다. 생성자 함수와 동일하게 this 객체에 속성을 할당하는 방식이다.
메소드는 constructor객체 아래에 동일하게 함수식으로 작성하면 된다.
pig_bar가 ice_cream의 하위객체라면 extends와 super키워드를 사용한다.
pig_bar만이 가지고 있는 속성이 있다면 constructor객체 안에 정의하면 된다.
super는 상위 클래스(ice_cream)를 호출할때 사용된다.