jeanpier_re
jeanpier_re

Reputation: 835

Is Object.prototype an object and is prototype somehow not?

When I type Object.prototype into the Chrome console it displays Object{}

If I assign it to a variable var proto = Object.prototype it displays Object{}

But if I check for it's prototype

var proto = Object.prototype
proto.prototype;

If proto is an Object{} and proto.prototype is undefined does that means thatObject() is an Object() that doesn't inherit from anything?

Also, would this be the same as Object.prototype.prototype?

Upvotes: 4

Views: 918

Answers (3)

boombox
boombox

Reputation: 2456

A lot can be said about prototypes, but the brief explanations below could help clarify the subject to make it easier to understand:

A) prototype is a property of functions.

Object.constructor returns function Function() { [native code] }, so we can get its prototype, just like how you were able to get the prototype of Object itself. This is because it is a function. typeof Object returns "function". On the other hand, typeof Object.prototype returns "object", so you were unable to get the prototype of Object.prototype.

// get prototype property of a function
var hello = function () {};
hello.prototype // hello {}

// get prototype property of an object
typeof hello.prototype // "object"
hello.prototype.prototype // undefined
hello = {};
hello.prototype // undefined

We can add properties and methods to a Constructor (which is a function) using the prototype property.

function Hello() {}
Hello.prototype.print = function () { console.log('hello'); };

// not using a constructor
var hello = Hello(); // undefined
hello.print(); // ERROR

// using a constructor
hello = new Hello(); // Hello {print: function}
hello.print(); // "hello"

B) __proto__ is a property of all objects (which includes functions).

Note that Object.__proto__ is equivalent to Object.constructor.prototype and Object.getPrototype(Object).

There is no prototype property of Object.prototype because it is not a function. But because it is an object, we can do Object.prototype.__proto__ which returns null. Getting null means we are at the end of the prototype chain.

Even functions have __proto__:

function Hello() {}
Hello.__proto__ // function Empty() {}

__proto__ is the internal prototype that is used by JS engines for inheritance/delegate chaining.

function Hello() {}
var hello = new Hello();

hello.__proto__ === Hello.prototype // true

Upvotes: 1

Dan Prince
Dan Prince

Reputation: 29999

Object.prototype is the furthest you can go up the prototype chain.

It Object.prototype has no prototype property, so what you see is undefined. In actuality, it's prototype is null. Which you can confirm with either the Object.getPrototypeOf method or the __proto__ property.

 Object.getPrototypeOf(Object.prototype); // null
 Object.prototype.__proto__; // null

The prototype property isn't a reliable way to traverse the prototype chain, as in many cases, it won't exist.

function MyObj() {}
MyObj.prototype.a = 3;
(new MyObj).prototype; // undefined

Object.create({ a: 3 }).prototype; // undefined

The __proto__ property is not a standard and may be removed from a future edition of ES. But in compatible browsers, it will work in the expected way.

Object.create({ a: 3 }).__proto__; // Object {a: 3}

Upvotes: 4

Paul S.
Paul S.

Reputation: 66364

If an Object has a prototype, the prototype is also an Object. These Objects all chain together until you reach null, which is the end of the prototype chain.

// Object is a constructor
Object.prototype; // Object {}, will be the prototype of `new Object`s
// Object.prototype is an Object
Object.getPrototypeOf(Object.prototype); // null, we are at the end of the chain

You should also note, however, that you can't keep accessing the obj.prototype property, as this is only applicable to Constructors, consider

function Foo() {
}
Foo.prototype; // Foo {}
// vs
(new Foo).prototype; // undefined

The correct way to find the prototype of an Object is by using Object.getPrototypeOf(obj),

Object.getPrototypeOf(new Foo) === Foo.prototype; // true

It may also be of note that legacy browsers may not support Object.getPrototypeOf, in which case many offer the property obj.__proto__. However, try to avoid using __proto__ outside of a shim for such browsers if you need to access the prototype chain.


Finally, using new with a Constructor isn't the only way to create this chain, you can set them up using Object.create

var a = Object.create(null),
    b = Object.create(a), // b will inherit from a
    c = Object.create(b); // c will inherit from b, hence also a
a.foo = 'foo';
b.bar = 'bar';

a instanceof Object; // false

a.bar; // undefined
c.foo + c.bar === 'foobar'; // true

Also consider

c.prototype; // undefined
// vs
Object.getPrototypeOf(c) === b; // true

Upvotes: 5

Related Questions