8

Simply put can I check if an object has a user defined prototype?

Example;

var A = function() {};

var B = function() {};

B.prototype = {

};

// Pseudocode
A.hasUserPrototype(); // False
B.hasUserPrototype(); // True

Is this possible?

GriffLab
  • 2,076
  • 3
  • 20
  • 21
  • 1
    What do you call user defined? A prototype that was not created by you? – Geeky Guy May 16 '13 at 20:50
  • 1
    You're only setting prototype as a property of those objects, there's no prototypal inheritance that will occur with the example you've provided. – zzzzBov May 16 '13 at 20:51
  • @zzzzBov I know this. But still in my example I have modified the prototype by assigning it an empty object, is there a way to check this? – GriffLab May 16 '13 at 20:53
  • @GriffLab, you have not modified "the prototype" you have only modified an attribute on the object that happens to be called "prototype". – zzzzBov May 16 '13 at 20:57
  • 1
    @GriffLab: "Prototype" is a very specific term in JavaScript. In your example, you have **not** changed the prototype of the object, you just have created a totally arbitrary property with the name `prototype`. Only the `prototype` property of **functions** is treated in a special way. If you just want to test whether a property exists or not, you should phrase the question differently (and I'm sure it's a duplicate then). – Felix Kling May 16 '13 at 20:57
  • I will re write my question in my code I do have functions, I just wrote this without thinking, thanks. – GriffLab May 16 '13 at 21:10
  • @GriffLab, when you declare a function, they're automatically instantiated with a new object as their `prototype` property. You don't need to re-declare prototype as an object, although it can be convenient for setting a bunch of methods all at once. – zzzzBov May 16 '13 at 21:12

3 Answers3

11

Assuming you want to find out whether an object is an instance of a custom constructor function, you can just compare its prototype against Object.prototype:

function hasUserPrototype(obj) {
    return Object.getPrototypeOf(obj) !== Object.prototype;
}

Or if you maintain the constructor property properly:

function hasUserPrototype(obj) {
    return obj.constructor !== Object;
}

This would also work in browsers which don't support Object.getPrototypeOf.

But both solutions would return true also for other native objects, like functions, regular expressions or dates. To get a "better" solution, you could compare the prototype or constructor against all native prototypes/constructors.


Update:

If you want to test whether a function has a user defined prototype value, then I'm afraid there is no way to detect this. The initial value is just a simple object with a special property (constructor). You could test whether this property exists (A.prototype.hasOwnProperty('constructor')), but if the person who set the prototype did it right, they properly added the constructor property after changing the prototype.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
1

Felix King accurately addressed the issue of inheritance, so I will address the concept of existing properties instead

If you're simply trying to check for the presence of a property named prototype on an object, you can use:

a.hasOwnProperty('prototype')

This will return true for:

a = {
    //the object has this property, even though
    //it will return undefined as a value
    prototype: undefined 
};

This assumes that the object is not being treated as a hashmap, where other properties, such as hasOwnProperty have been set, otherwise, a safer way of checking for the presence of a property is:

Object.prototype.hasOwnProperty.call(a, 'prototype')

This can be turned into a generic function as:

has = (function (h) {
    "use strict";
    return function (obj, prop) {
        h.call(obj, prop);
    };
}(Object.prototype.hasOwnProperty));

and used as:

has(a, 'prototype');
zzzzBov
  • 174,988
  • 54
  • 320
  • 367
0

For A object prototype will be undefined:

typeof A.prototype == "undefined" // true
typeof B.prototype == "undefined" // false
Pavel Strakhov
  • 39,123
  • 5
  • 88
  • 127
  • I'm afraid of `undefined` being defined. – Pavel Strakhov May 16 '13 at 20:57
  • @Riateche I agree with you on this. – GriffLab May 16 '13 at 20:58
  • 1
    really? i'm all for defensive coding, but i've never see anyone redefine undefined to something else... – dandavis May 16 '13 at 20:59
  • `A.prototype = undefined` will set a property called `prototype` on the object, and will return an incorrect value with this code. – zzzzBov May 16 '13 at 20:59
  • @dandavis: That's not necessarily true. I made some tests recently and it turned out that both ways are equally fast, at least in Chrome. `typeof` is not a function but an operator and hence probably quite fast. – Felix Kling May 16 '13 at 20:59
  • Notice that this does not work for functions, which have a `prototype` by default… – Bergi May 16 '13 at 21:08
  • @Bergi, actually, it *does* work for functions, because the object has its own prototype property. Conceptually it's identical to a user-defined prototype property. – zzzzBov May 16 '13 at 21:10