728x90
프로토타입 메소드와 __proto__ 가 없는 객체
__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);
과 같이 객체를 만들면 된다.
이렇게 만들면 __proto__
는 getter와 setter를 상속받지 않기 때문에 평범한 데이터 프로퍼티처럼 처리가 되기 때문이다. 이런 객체는 일반 객체 {...} 보다 훨씬 단순하기에 '아주 단순한' 혹은 '순수 사전식' 객체라고 부른다.
추가
Object.create를 사용하면 for..in 을 사용해 프로퍼티를 복사하는 것 보다 효과적으로 객체를 복제 가능하다.
// obj와 완벽하게 동일한 얕은 사본
let clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));
728x90
댓글