dkugappi
dkugappi

Reputation: 2764

JavaScript: how to access the prototype of a constructor function?

Maybe silly question to the JS gurus and ninjas out there but here goes:

My understanding of the prototype object/property of an object is that it is a blueprint for future instances of an object. Given this, shouldn't a newly created instance of an object be identical to the constructor object that created it?

var x = new Object(); 
console.log(x === Object.prototype); // returns false. why?? 

* UPDATE *

So understanding that this will return false because they are referencing different things, I still find that new Object() and Object.prototype contain a different number of properties. So to refine my question: How do I correctly check the number of properties in a prototype Object; how do I iterate through them?

The reason I got confused by this is that if I create a simple constructor function:

function Circle(){
   this.tail = "yes, has tail";
}

and want to get the number of properties it has, doing something like:

console.log(Object.getOwnPropertyNames(Circle.prototype)); 
// returns "constructor", I expected it to return "tail"

Upvotes: 0

Views: 478

Answers (4)

Mike Samuel
Mike Samuel

Reputation: 120586

=== does not answer the question of whether two things are equivalent, but whether they are references to the same object.

x and Object.prototype in your example may have the same properties, so you can call them equivalent, but they are two different objects.

If you do

x.foo = 3

they are now no longer equivalent, because they were two different objects. You changed one but not the other.

If

x === Object.prototype

were true, then

x.foo === Object.prototype.foo

would be the same regardless of what you assign to x.foo or Object.prototype.foo.

EDIT:

function Circle(){ this.tail = "yes, has tail"; }

console.log(Object.getOwnPropertyNames(Circle.prototype)); 
// returns "constructor", I expected it to return "tail"

There is no tail property on Circle.prototype because you have never done Circle.prototype.tail = ...;. You define tail only on Circle instances via this.tail = ...;.

I still find that new Object() and Object.prototype contain a different number of properties.

You are also doing getOwnPropertyNames. The own properties are those that are not inherited from the prototype, so by using that function on x you are explicitly excluding all the properties of Object.prototype.

The docs for hasOwnProperty explain "own property" pretty well:

This method can be used to determine whether an object has the specified property as a direct property of that object; unlike the in operator, this method does not check down the object's prototype chain.

Upvotes: 2

Jonathan Lonowski
Jonathan Lonowski

Reputation: 123573

Regarding your update:

this within a constructor function is the instance created with the new keyword, not the prototype.

So, in the case of your snippet...

function Circle(){
   this.tail = "yes, has tail";
}

Setting this.tail is similar to:

var c = new Circle();
c.tail = "yes, has tail";

tail is only a property of the instance.

To set tail on the prototype, you must use:

Circle.prototype.tail = "yes, has tail";

Now, "Own" properties are those set directly on the instance. These counter and override prototype properties of the same name:

function Circle() {
    // give the instance its "own" `foo` property
    this.foo = 'qux';
}

Circle.prototype.foo = 'foo';
Circle.prototype.bar = 'bar';

var c = new Circle();

console.log(c.foo); // the overridden "qux", not the inherited "foo"
console.log(c.bar); // "bar", as inherited

// yet the prototype still persists to have its "own" `foo`
console.log(Circle.prototype.foo); // "foo"

// While the instance has keys for all involved properties
console.log(Object.keys(c)); // [ "foo", "bar" ]

// It also retains which are its "own"
console.log(Object.getOwnPropertyNames(c)); // [ "foo" ]

Upvotes: 0

Frizi
Frizi

Reputation: 2940

x is an instance of "Object". You probably want to check if x has a Object as constructor. Prototype isn't constructor. Try this

var x = new Object(); 
console.log(x.constructor === Object);

Upvotes: 0

Raynos
Raynos

Reputation: 169551

console.log(Object.getPrototypeOf(x) === Object.prototype); // true

If you want to get the hidden property [[Prototype]] that points to the next element in the prototype chain for an object just call Object.getPrototypeOf.

Also you mis-understand how the prototype chain works.

For any given object, if you look up a property it will first look at that object. It will then (recursively) look at the objects [[Prototype]] value for whether it has that property.

Example prototype chains :

var o = new Object();
// o -> Object.prototype -> null
var a = new Array();
// a -> Array.prototype -> Object.prototype -> null
var Super = function () {};
var Child = function () {};
Child.prototype = Object.create(Super.prototype);
var c = new Child();
// c -> Child.prototype -> Super.prototype -> Object.prototype -> null

Upvotes: 1

Related Questions