Object.getPrototypeOf
이 글은 John Resig의 'Object.getPrototypeOf'을 번역한 것이다.
Object.getPrototypeOf
역사적으로 __proto__
는 편리하기 때문에 많은 사랑을 받았다. __proto__
는 객체의 constructor 함수의 property에 접근하는 방법이다. 사용하기 쉽지만 좀 지저분하다. 다음의 코드는 true이다:
"test".__proto__ === String.prototype
// Another alternative, not using __proto__
// Only works when constructor isn't changed
"test".constructor.prototype === String.prototype
Object.getPrototypeOf(object)은 ECMAScript 3.1 표준에 추가될 것 같다(역주, 실제로 ECMAScript 5에). 그리고 Firefox에서 이제 막 구현했다.
이제 막 표준화된 이 기능은 어떻게 사용해야 할까?
instanceOf
instanceOf를 JavaScript로 구현한다면 다음과 같다:
function instanceOf(object, constructor) {
while (object != null) {
if (object == constructor.prototype)
return true;
object = Object.getPrototypeOf(object);
}
return false;
}
instanceOf("test", String);
instanceOf(true, Boolean);
prototype chain을 따라서 constructor의 prototype이 있는지 찾는다. 이 코드는 getPrototypeOf을 설명하기에 좋다.
Super Methods
getPrototypeOf()를 super 키워드 처럼 사용할 수 있다. 코드를 보자:
function Person(){}
Person.prototype.kick = function(type){
alert(type + " kick!");
}
function Norris(){}
// Inherit properties from Person
Norris.prototype = new Person();
Norris.prototype.kick = function(){
Object.getPrototypeOf(this).kick("Roundhouse");
};
Object.getPrototypeOf(this)를 통해서 원래의 kick method에 접근 할 수 있다. 이 예제에서는 getPrototypeOf()이용하여 kick method를 override했다.
Cross-Browser Implementation
브라우저들이 Object.getPrototypeOf를 구현할 때까지 다음과 같은 코드를 사용할 수 있다:
if ( typeof Object.getPrototypeOf !== "function" ) {
if ( typeof "test".__proto__ === "object" ) {
Object.getPrototypeOf = function(object){
return object.__proto__;
};
} else {
Object.getPrototypeOf = function(object){
// May break if the constructor has been tampered with
return object.constructor.prototype;
};
}
}
.constuctor property는 mutable이기 때문에 이 코드는 완벽하지 않다. 사용자가 갑자기 .constructor property의 값을 바꿔 버릴 수도 있다. 그렇지만 브라우저들이 구현할때까지 충분히 쓸만할 것이다.
Why Object.getPrototypeOf?
왜 'test'.getPrototypeOf()가 아니라 Object.getPrototypeOf('test')일까? __proto__
처럼 property도 아니다. 왜? 객체의 method나 property인 편이 더 편리할 것 같지만 실제로는 그렇지 않다.
일단 다음과 같은 예제부터 살펴보자:
var obj = { getPrototypeOf: "blah" };
사용자가 이렇게 정의해 버리면 getPrototypeOf()은 메소드가 아니라서 호출될 수 없다. 그러니까 개발자들은 항상 Object.getPrototypeOf()라고 사용해야 한다. getPrototypeOf()가 필요한 때는 보통 fallback같은 것을 만들 때이다. 즉, 일반적으로 필요하지 않기 때문에 모든 객채의 property일 필요는 없는 것이다.
그리고 누구도 Object의 Prototype(Object.prototype.getPrototypeOf = ...;)을 확장하는 것 같은 사악한 짓은 하지 않을 것이기 때문에 예전 코드를 지원하기도 쉽다.