public

Polyfill for Object.getPrototypeOf

  • Download Gist
Object.getPrototypeOf.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
 
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;
}
}
}());

Here is some code that demonstrates that this polyfill is incorrect for IE8 and lower:

if (typeof Object.getPrototypeOf2 != "function")(function(){

Object.getPrototypeOf2 =
    (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;
    }
}

}());

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');
}

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));

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.