자바스크립트에서 상속은 존재하는 코드를 재사용 가능하게 해준다. 부모 생성자의 기능을 물려받거나 새로운 기능을 추가할 수 있다.
프로토타입 체이닝이 아주 대표적인 상속의 예시이다. 모든 함수는 prototype
프로퍼티를 가지며, 이는 객체이다. 함수가 new
오퍼레이터와 함께 호출되면, 객체가 생성되고 객체는 __proto__
link로 프로토타입 객체와 연결된다. 이 링크는 프로토타입 객체의 프로퍼티를 사용할 수 있게 해준다. 프로토타입 객체도 역시 객체이기 때문에 프로토타입 객체를 가지고 있다. 이것이 프로토타입 체인이다.
A 객체에 없는 프로퍼티를 B에서, B에서도 없으면 C에서, ...., 가장 상위레벨의 Object
객체에서 체이닝은 끝난다. 이러한 방식으로 상속이 이루어지며, A 객체는 상속 체인에 있는 모든 프로퍼티에 접근할 수 있다.
function Shape(){
this.name = 'shape';
this.toString = function() {return this.name;};
}
function TwoDShape(){
this.name = '2D shape';
}
function Triangle(side, height) {
this.name = 'Triangle';
this.side = side;
this.height = height;
this.getArea = function(){return this.side * this.height / 2;};
}
TwoDShape.prototype = new Shape();
Triangle.prototype = new TwoDShape();
TwodDShape
의 프로토타입 객체를 Shape
생성자 함수로 new
키워드와 함께 할당하였다. 그리고 Triangle
의 프로토타입 객체를 TwoDShape
생성자 함수로 할당하였다. 상속이 이루어진 후에는 Shape()
를 수정,오버라이딩,삭제를 하여도 TwoDShape
에는 전혀 영향이 없다.
그러나 prototype
을 새로운 객체로 재할당하는경우, constructor
프로퍼티는 더이상 기존의 생성자 함수를 가리키지 않는 문제가 생긴다. 따라서 상속 이후에 constructor
를 리셋해주는 것이 좋다.
TwoDShape.prototype.constructor = TwoDShape ;
Triangle.prototype.constructor = Triangle ;
getArea
메서드가 작동하는지 확인해보자.
let my = new Triangle(5,10);
my.getArea();
// 25
toString
메서드를 보자.
my.toString()
// "Triangle"
Triangle
에는 없는 toString
메서드가 정상적으로 작동된다. 프로토타입 상속에 의해서 Shape
의 toString
메서드를 가져오고, this
가 my
객체를 바인딩하여 Triangle
이 출력된다.
function Shape(){
this.name = 'shape';
}
new Shape()
로 객체를 생성하게되면, 모든 객체마다 name
프로퍼티를 메모리에 저장하게 된다. 만약에, name
프로퍼티 값이 바뀔일이 없는 값이라면, 프로토타입에 저장을 하는 것이 효율적이다. 그렇게 되면 new Shape()
로 생성된 객체는 name
프로퍼티를 프로토타입에서 상속받아 온다.
객체에서 다이렉트로 상속받는 방법말고도, constructor
을 이용하여 상속하는 방법도 있다. call
, apply
를 이용하는 방법이다.
function Shape(id) {
this.id = id;
}
Shape.prototype.name = 'shape';
Shape.prototype.toString = function(){return this.name;};
function Triangle() {
Shape.apply(this, arguments);
}
Triangle.prototype.name = 'Triangle';