-
-
Save subtleGradient/1052392 to your computer and use it in GitHub Desktop.
Polyfill for Object.getPrototypeOf
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
if (typeof Object.getPrototypeOf != "function")(function(){ | |
Object.getPrototypeOf = | |
(typeof "".__proto__ == "object") | |
? function(object){ | |
return getPrototypeValue(object, '__proto__'); | |
} | |
: function(object){ | |
return getPrototypeValue(object, 'constructor').prototype; | |
} | |
; | |
var hasOwnProperty = Object.prototype.hasOwnProperty; | |
function getPrototypeValue(object, propertyName){ | |
try{ | |
if (hasOwnProperty.call(object, propertyName)){ | |
var ownValue = object[propertyName]; | |
delete object[propertyName]; | |
} | |
return object[propertyName]; | |
} | |
catch(e){throw e} | |
finally{ | |
object[propertyName] = ownValue; | |
} | |
} | |
}()); |
Dang. Back to the drawing board I guess.
Even though it might not work for returning the actual prototype, the idea works fine for determining the constructor of the prototype (but beware of the bug that causes object[propertyName] to be assigned to undefined
if the property did not exist):
function getPrototypeValue(object, propertyName){
if (Object.prototype.hasOwnProperty.call(object, propertyName)){
try{
var ownValue = object[propertyName];
delete object[propertyName];
return object[propertyName];
}
finally{
object[propertyName] = ownValue;
}
}
return object[propertyName];
}
function getBaseType(type) {
return getPrototypeValue(type.prototype, 'constructor');
}
function Parent() {}
function Child1() {}
Child1.prototype = new Parent();
function Child2() {}
Child2.prototype = new Parent();
Child2.prototype.constructor = Child2;
alert((getBaseType(Child1) === Parent) + ", " + (getBaseType(Child2) === Parent) + ", " + (getBaseType(Parent) === Object));
alert((Parent.prototype.constructor === Parent) + ", " + (Child1.prototype.constructor === Parent) + ", " + (Child2.prototype.constructor === Child2));
How about this
if (typeof Object.getPrototypeOf === 'undefined') {
Object.getPrototypeOf = function (obj) {
var t = typeof obj;
if (!obj || (t !== 'object' && t !== 'function')) {
throw new TypeError('not and object');
}
return obj.__proto__;
};
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Here is some code that demonstrates that this polyfill is incorrect for IE8 and lower:
if (typeof Object.getPrototypeOf2 != "function")(function(){
}());
function Parent() {}
var parent = new Parent();
function Child() {}
Child.prototype = parent;
var child = new Child();
if (Object.getPrototypeOf2(child) != parent) {
alert('fail 1'); // fail in ie8 and lower
}
else {
alert('win 1');
}
if (Object.getPrototypeOf2(child) == Parent.prototype) {
alert('fail 2'); // fail in ie8 and lower
}
else {
alert('win 2');
}