kjo
kjo

Reputation: 35301

Difference between Object.getPrototypeOf(x) and x.constructor.prototype?

For most values of x that I have tested, the following evaluates to true:

Object.getPrototypeOf(x) === x.constructor.prototype

...but there are a few exceptions: if x is a string, the LHS of the expression above fails with an error like

TypeError: "abc" is not an object

...although, e.g., "abc".constructor.prototype evaluates to String.prototype. One gets analogous results if x is a number or a boolean.

What's going on? Are there more exceptions to the identity shown earlier?

More to the point, the above suggests that x.constructor.prototype is more robust than Object.getPrototypeOf(x).

Is there any good reason not to use x.constructor.prototype exclusively and forget entirely about the Object.getPrototypeOf(x)?

Upvotes: 4

Views: 146

Answers (2)

Joon
Joon

Reputation: 9884

Object.getPrototypeOf is not supported by older browsers where as x.constructor.prototype is more cross-browser solution.

However, if available it is more reliable to use Object.getPrototypeOf because x.constructor can be changed like so: x.constructor = 'my new value';

I suggest you to create this polyfill function:

if (!Object.getPrototypeOf) {
    Object.getPrototypeOf = function(o) { return o.__proto__ || o.constructor.prototype; };
}

Upvotes: 0

Niet the Dark Absol
Niet the Dark Absol

Reputation: 324620

Strings (and other primitives) can behave a little weirdly.

Basically, when you try to access a property of a primitive, it is boxed in a Just-In-Time fashion using its Object equivalent, and then the property of that object is returned.

So in this case, when you try to access "abc".constructor, what's actually happening is the same as new String("abc").constructor (which of course returns the String object).

On the other hand, Object.getPrototypeOf does no such boxing, instead returning an error if you pass it anything that isn't an object.

As you suggest, x.constructor.prototype does seem to be a more reliable method of determining the constructor of something, since it does handle this "boxing" case. That said, personally I can't think of any real situation where something like this might be needed, since... well, typically, you already know what type something is. It's the same reason I don't see any real point in using === most of the time.

Upvotes: 1

Related Questions