(JS) Object.create()

호두파파·2021년 3월 18일
0

JavaScript

목록 보기
25/25


자바스크립트는 상속을 통해 부모 객체의 기능을 물려받고, 새로운 프로퍼티를 추가할 수 있다. 이러한 상속의 기능을 제대로 구현하기 위해 Object.create()를 활용해야 한다.

정의

Object.create()메서드는 지정된 프로토타입 객체 및 속성(property)을 갖는 새 객체를 만든다.
Object.create(proto[, propertiesObject])

매개변수

  • proto : 새로 만든 객체의 프로토타입이어야 할 객체.
  • propertiesObject(optional) : undefined가 아니면, 자신의 속성(자체에 정의되어 프로토타입 체인에서 열거가능하지 않은 속성)이 열거가능한 객체는 해당 속성명으로 새로 만든 객채에 추가될 속성 설명자를 지정할 수 있다.

반환값

지정된 프로토타입 개체와 속성을 갖는 새로운 개체

// 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()
//   ► ....
  • Ractangle 프로토타입 객체에는 constructor 프로퍼티를 가지고 있고,
    그 프로퍼티는 자신을 생성한 생성자함수 Rectangle를 가리키고 있다.
  • proto를 확인하면, Rectangle의 프로토타입 객체의 부모객체인 Object 프로토타입 객체가 나온다.

proto 혹은 [[prototype]]

  • 함수를 포함한 모든 객체가 가지고 있는 인터널 슬롯이다.
  • 객체의 입장에서 자신의 부모역할을 하는 프로토타입 객체를 가리키며 함수 객체의 경우 Function.prototype을 가리킨다.

Object.create()함수를 사용

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
  • Rectangle 프로토타입 객체를 보면, {}라고 빈 객체가 생성되어 있다.
    MDN이 말하던 "새 객체"이다.
  • Object.create()함수는 인자로 전달된 shape 프로토타입 객체를 새로 만들어진 객체의 프로토타입 객체로 할당한다. 그래서 프로토타입 체인을 통해 shape 프로토타입 Move 메소드를 사용할 수 있는 것이다.

More Attention

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() 없이 prototype 객체 연결하기

// 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);
//   }
  • Object.create()를 사용하지 않으면,
    Rectangle 프로토타입 객체의 constructor 프로퍼티는 Rectagle 생성자 함수가 아닌 shape 생성자 함수를 참조한다. 즉, Rectangle 생성자 함수로 새로운 인스턴스를 만들게 되면 shape 생성자 함수로 새로운 객체가 만들어진다.
  • 이 문제를 해결하기 위해 Rectangle 생성자 함수로 재 할당을 한다.
    그러면, "shape 생성자 함수가 아닌 Rectangle 생성자 함수를 가리키게 된다.
    즉, shape 생성자 함수로 새로운 인스턴스를 만들면, Rectangle 생성자 함수로 새로운 객체가 만들어진다.
profile
안녕하세요 주니어 프론트엔드 개발자 양윤성입니다.

0개의 댓글