19

This is a purely trivial question for academic value:

If I create a new object, either by doing:

var o = { x:5, y:6 };

or

var o = Object.create({ x:5, y:6 });

when I query the o.prototype property, I get undefined. I thought that any newly created object automatically inherits the Object.prototype prototype.

Furthermore, invoking toString(), (a method of Object.prototype) on this object works just fine, implying that o does inherit from Object.prototype. So why do I get undefined?

4
  • 6
    The "prototype" property of your object "o" is not the way that the runtime system finds its prototype object. There are internal properties to keep track of that; it's all very confusing. The question is asked a lot, and if I can find one of the good blog posts on the topic I'll link it. Commented Oct 28, 2011 at 12:26
  • Your object is an instance, whereas a function is the constructor with the prototype property available. If you want to get the prototype of an instance, use Object.getPrototypeOf(o). Commented Oct 28, 2011 at 12:36
  • 2
    @Alex Nabokov: With `, so e.g. `test` will yield test. (To put those ` literally, escape them.) Commented Oct 28, 2011 at 12:39
  • @pimvdb So I went ahead and used the Object.getPrototypeOf(o) method: x = Object.getPrototypeOf(o); for (prop in x) { console.log(x); } and I get some really bizarre behaviour, I get object Object back for each property, instead of x and y. Curiously doing the same thing but doing console.log(x[prop]) returns 5, and 6. Commented Oct 28, 2011 at 12:47

3 Answers 3

20

There is a difference between instances and their constructors.

When creating an object like {a: 1}, you're creating an instance of the Object constructor. Object.prototype is indeed available, and all functions inside that prototype are available:

var o = {a: 1};
o.hasOwnProperty === Object.prototype.hasOwnProperty; // true

But Object.create does something different. It creates an instance (an object), but inserts an additional prototype chain:

var o = {a: 1};
var p = Object.create(o);

The chain will be:

Object.prototype  -  o  -  p

This means that:

p.hasOwnProperty === Object.prototype.hasOwnProperty; // true
p.a === o.a; // true

To get the prototype "under" an instance, you can use Object.getPrototypeOf:

var o = {a: 1};
var p = Object.create(o);

Object.getPrototypeOf(p) === o; // true
Object.getPrototypeOf(o) === Object.prototype; // true

(Previously, you could access an instance's prototype with o.__proto__, but this has been deprecated.)

Note that you could also access the prototype as follows:

o.constructor === Object; // true

So:

o.constructor.prototype === Object.prototype // true
o.constructor.prototype === Object.getPrototypeOf(o); // true

This fails for Object.create-created objects because they do not have a constructor (or rather, their constructor is Object and not what you passed to Object.create because the constructor function is absent).

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the detailed answer. The one thing I don't quite get is why o.prototype (which as you say above is an instance of the Object constructor) returns undefined, and Object.getPrototypeOf(o) returns the prototype. Aren't they in theory the same thing and should be pointing to the same prototype object of o?
@Alex Nabokov: No - constructors have .prototype and instances have Object.getPrototypeOf. So with an object o there is Object.prototype (constructor) and Object.getPrototypeOf(o) (instance). These two do refer to the same thing.
you said "When creating an object like {a: 1}, you're creating an instance of the Object constructor". wouldn't it be more correct to say "... you're creating a new instance using the Object constructor"? I'm not trying to bash your answer but trying to understand this darn language Javascript.
5

Not a direct answer, but knowledge that everybody, who deal with inheritance in Javascript, should have.

Prototype inheritance in Javascript is a tricky concept. Up until now, it has been impossible to create an empty object (by empty I mean lacking even properties form Object via prototype). So this means that creating a new object always had a link to the original Object prototype. However, according to the specification, the prototype chain of an object instance isn't visible, but some vendors have decided to implement their own proprietary object properties so that you could follow it, but it's highly recommended not to use it in production code.

The following sample code demonstrates just two ways of creating an object instance.

var someObject = {};
var otherObject = new Object();
var thirdObject = Object.create({});

Even though you don't manually add object properties to empty curly braces, you still get automatically added prototype chain. The same goes for the second example. To visualize it better, you can type those lines into Chrome console and then enter either someObject, otherObject or thirdObject to see details. Chrome shows the prototype chain by adding a proprietary property __proto__ which you can expand to see what is inherited and where it's from. If you executed something like

Object.prototype.sayHello = function() {
  alert('hello');
};

you would be able to call it on all instances, by executing otherObject.sayHello().

However, using something that was implemented quite recently (therefore not supported by all browsers), you can actually create a truly empty object instance (doesn't inherit even from Object itself).

var emptyObject = Object.create(null);

When you enter it into Chrome console and then expand the emptyObject to see it's prototype chain, you can see that it doesn't exist. So even if you implemented the sayHello function to Object prototype, it would be impossible to call emptyObject.sayHello() since emptyObject does not inherit from Object prototype.

Hope it helps a bit with the general idea.

2 Comments

+1 You could do it previously as: var o = {}; o.__proto__ = null; but it is deprecated anyway.
@pimvdb to my knowledge __proto__ is neither standardized nor supported by all browsers.
5

JavaScript has two types of objects: function object and non-function object. Conceptually, all objects have a prototype (NOT A PROTOTYPE PROPERTY). Internally, JavaScript names an object's prototype as [[Prototype]].

There are two approaches to get any object (including non-function object)'s [[prototype]]: the Object.getPrototypeOf() method and the __proto__ property. The __proto__ property is supported by many browsers and Node.js. It is to be standardized in ECMAScript 6.

Only a function (a callable) object has the prototype property. This prototype property is a regular property that has no direct relationship with the function's own [[prototype]]. When used as a constructor ( after the new operator), the function's prototype property will be assigned to the [[Prototype]] of a newly created object. In a non-function object, the prototype property is undefined . For example,

var objectOne = {x: 5}, objectTwo = Object.create({y: 6});

Both objectOne and objectTwo are non-function objects therefore they don't have a prototype property.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.