자바스크립트는 상속을 통해 부모 객체의 기능을 물려받고, 새로운 프로퍼티를 추가할 수 있다. 이러한 상속의 기능을 제대로 구현하기 위해 Object.create()를 활용해야 한다.
Object.create()
메서드는 지정된 프로토타입 객체 및 속성(property)을 갖는 새 객체를 만든다.
Object.create(proto[, propertiesObject])
지정된 프로토타입 개체와 속성을 갖는 새로운 개체
// Shape - 상위클래스
function Shape() {
this.x = 0;
this.y = 0;
};
// 상위클래스 메서드
Shape.prototype.move = function(x, y) {
this.x += x;
this.y += y;
console.info('Shape moved.');
};
// Rectangle - 하위클래스
function Rectangle() {
Shape.call(this);
};
console.log를 확인해보면 하단과 같이 확인된다.
현재 상태에서 console.log를 확인해보자.
console.log(Rectangle.prototype);
// ▼ {constructor: ƒ}
// ► constructor: ƒ Rectangle() -> constructor 프로퍼티가 Rectangle 생성자함수를 가리키고 있다.
// ► __proto__: Object -> 프로토타입 체인으로 부모 객체와 연결된다.
console.log(Rectangle.prototype.__proto__);
// ▼ {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ …}
// ► constructor: ƒ Object()
// ► ....
proto 혹은 [[prototype]]
- 함수를 포함한 모든 객체가 가지고 있는 인터널 슬롯이다.
- 객체의 입장에서 자신의 부모역할을 하는 프로토타입 객체를 가리키며 함수 객체의 경우 Function.prototype을 가리킨다.
Rectangle.prototype = Object.create(Shape.prototype);
console.log(Rectangle.prototype);
// ▼ Shape {} -> 빈 객체가 만들어졌다! 이전에는 constructor 프로퍼티가 있는 객체였다.
// ► __proto__: Object
console.log(Rectangle.prototype.__proto__);
// ▼ {move: ƒ, constructor: ƒ}
// ► move: ƒ (x, y) -> Shape 프로토타입의 Move 메소드가 생긴것을 확인할 수 있다.
// ► constructor: ƒ Shape()
// ► __proto__: Object
Object.create()을 사용할 경우, 새로 만들어진 객체에는 construnctor 프로퍼티가 없다
그래서 constructor 프로퍼티를 만들고, 그 프로퍼티가 자신을 생성한 함수를 가리키도록 재 할당해줘야 한다.
//Object.create()를 다시 재사용한다.
//새로 만들어진 프로토타입 객체는 자기 자신을 생성한 함수를 가리키는 constructor 프로퍼티가 없다.
// 새로 만들어줘야 한다.
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
console.log(Rectangle.prototype);
// ▼ Shape {constructor: ƒ} -> 생성자 함수가 생긴것 확인할 수 있다.
// ► constructor: ƒ Rectangle() -> 새로 만들어준 constructor 프로퍼티다.
// ► __proto__: Object
console.log(Rectangle.prototype.__proto__);
// ▼ {move: ƒ, constructor: ƒ}
// ► move: ƒ (x, y)
// ► constructor: ƒ Shape()
// ► __proto__: Object
// Object.create()를 사용하지 않고 바로 할당
Rectangle.prototype = shape.prototype;
console.log(Rectangle.prototype);
// ► {move: ƒ, constructor: ƒ} -> Shape 프로토객체의 move 메소드가 잘 보인다.
// Reactangle의 프로토타입 객체의 constructor 프로퍼티가 Shape로 연결되어 있다.
console.log(Rectangle.prototype.constructor);
// ► ƒ Shape() { -> Shape가 나온다.
// this.x = 0;
// this.y = 0;
// }
//다시 재할당
Rectangle.prototype.constructor = Rectangle;
//console.log로 확인하면 Rectangle로 잘 할당되어 있다.
console.log(Rectangle.prototype.constructor);
// ► ƒ Rectangle() { -> 오! Rectangle이 잘 나온다.
// Shape.call(this);
// }
//문제는 Shape의 프로토타입 객체의 constructor 프로퍼티도 Rectangle 함수로 바뀐다.
console.log(Shape.prototype.constructor)
// ► ƒ Rectangle() { -> shape가 확인 되지 않는다.
// Shape.call(this);
// }