Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save subtleGradient/1052392 to your computer and use it in GitHub Desktop.
Save subtleGradient/1052392 to your computer and use it in GitHub Desktop.
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
Copy link

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
Copy link
Author

Dang. Back to the drawing board I guess.

@erik-kallen
Copy link

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

@hueitan
Copy link

hueitan 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