Create a gist now

Instantly share code, notes, and snippets.

Polyfill for Object.getPrototypeOf
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;
}
}
}());
@incompl
incompl commented Oct 20, 2011

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

@subtleGradient
Owner

Dang. Back to the drawing board I guess.

@erik-kallen

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));
@huei90
huei90 commented Jun 3, 2014

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