본문 바로가기
Programming/JavaScript

Javascript - 프로토타입 메서드와 __proto__ 가 없는 객체

by Muko 2020. 5. 27.

프로토타입 메소드와 __proto__ 가 없는 객체

image

__proto__ 는 객체의 프로퍼티가 아니라 Object.prototype 의 접근자 프로퍼티이다. 그래서 obj.__proto__ 를 읽거나 쓸 때는 이에 대응하는 getter, setter가 프로토타입에서 호출되고 [[Prototype]] 을 가져오거나 설정한다. 따라서 __proto__[[Prototype]] 에 접근하기 위한 방법으로 쓰여왔다.

그런데 __proto__ 보다 모던한 메서드가 있다.

let animal = {
  eats: true
};

// 프로토타입이 animal인 새로운 객체를 생성합니다.
let rabbit = Object.create(animal);

alert(rabbit.eats); // true
alert(Object.getPrototypeOf(rabbit) === animal); // true

Object.setPrototypeOf(rabbit, {}); // rabbit의 프로토타입을 {}으로 바꿉니다.
  • Object.create(proto [, description]) - [[Prototype]]proto 를 참조하는 빈 객체를 만든다. 이 때 프로퍼티 설명자를 추가로 넘길 수 있다.
  • Object.getPrototypeOf(obj) - obj의 [[Prototype]] 을 반환한다.
  • Object.setPrototypeOf(obj, proto) - obj의 [[Prototype]]proto 가 되도록 설정한다.

아주 단순한 객체

객체는 키-값 쌍을 저장할 수 있는 연관 배열이지만, 커스텀 사전을 만드는 것과 같이 사용자가 직접 입력한 키를 가지고 객체를 만들다보면 __proto__ 는 키로 사용할 수 없다는 결함이 발견된다.

let obj = {};

let key = prompt("입력하고자 하는 key는 무엇인가요?", "__proto__");
obj[key] = "...값...";

alert(obj[key]); // "...값..."이 아닌 [object Object]가 출력됩니다.

__proto__ 는 항상 객체이거나 null 이어야 하기 때문에 문자열은 프로토타입이 될 수 없다.

만약 할당 값이 객체일 경우에는 프로토타입이 바뀔 수 있는데, 자바스크립트 엔진은 객체의 프로토타입이 변경되지 않는다는 가정하에서 최적화를 진행하기 때문에 치명적인 결함의 원인이 될 수 있다.

이럴 때는

let obj = Object.create(null);

과 같이 객체를 만들면 된다.

image

이렇게 만들면 __proto__ 는 getter와 setter를 상속받지 않기 때문에 평범한 데이터 프로퍼티처럼 처리가 되기 때문이다. 이런 객체는 일반 객체 {...} 보다 훨씬 단순하기에 '아주 단순한' 혹은 '순수 사전식' 객체라고 부른다.

추가

Object.create를 사용하면 for..in 을 사용해 프로퍼티를 복사하는 것 보다 효과적으로 객체를 복제 가능하다.

// obj와 완벽하게 동일한 얕은 사본
let clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));

댓글0