var someObj = function() { }
var p = new someObj();
alert(someObj.prototype); // This works
alert(p.prototype); // UNDEFINED, but why?
someObj.prototype.model= "Nissan";
alert(p.model); // This works! I understand the dynamic nature of prototypes, but doesn't that mean that p.prototype === someObj.prototype?
Why is this so? Since "p" is an instance of "someObj", why is the prototype undefined? I mean, when I add a property to "someObj" prototype, it is accessible to "p", so why is the prototype not accessible?
var someObj = function() { }
var p = new someObj();
alert(someObj.prototype); // This works
alert(p.prototype); // UNDEFINED, but why?
someObj.prototype.model= "Nissan";
alert(p.model); // This works! I understand the dynamic nature of prototypes, but doesn't that mean that p.prototype === someObj.prototype?
Why is this so? Since "p" is an instance of "someObj", why is the prototype undefined? I mean, when I add a property to "someObj" prototype, it is accessible to "p", so why is the prototype not accessible?
Share Improve this question asked Apr 26, 2012 at 8:33 Taha AhmadTaha Ahmad 5594 silver badges18 bronze badges5 Answers
Reset to default 11The important thing here is that the prototype
property of function objects is not the prototype of an object. It's the object that will be assigned as the prototype of an object you create via new someObj
. Prior to ES5, you can't directly access the prototype of an object; as of ES5, you can, via Object.getPrototypeOf
.
Re
alert(p.prototype); // UNDEFINED, but why?
The reason is that the p
object doesn't have a property called "prototype". It has an underlying prototype, but that's not how you access it.
All function objects have a property called prototype
so that if they're used as constructor functions, we can define what the properties of the underlying prototype of the objects created by those constructors will be. This may help:
function Foo() {
}
Foo.prototype.answer = 42;
console.log(Foo.prototype.answer); // "42"
var f = new Foo();
console.log(f.answer); // "42"
That last line works like this:
- Get the
f
object. - Does
f
have its own property called "answer"? - No, does
f
have a prototype? - Yes, does the prototype have its own property called "answer"?
- Yes, return the value of that property.
You've mentioned Object.create
in the title of your question. It's important to understand that Object.create
is quite separate from constructor functions. It was added to the language so that if you preferred not to use constructor functions, you didn't have to, but could still set the prototype of an object — directly, when you create that object.
That's because prototype
is a property of the constructor function, not a property of itself. However, the prototype
object has a reference to the constructor, so you can access an object's prototype
via its constructor
property:
function Foo() {}
Foo.prototype.foo = "bar";
var c = new Foo;
console.log( c.constructor === Foo ); // true
console.log( c.constructor.prototype ); // { foo: 'bar' }
However, this will not work if you overwrite the initial prototype
property of the constructor function:
function Foo() {}
// I overwrite the prototype property, so I lose the initial reference
// to the constructor.
Foo.prototype = {
foo: "bar"
};
var c = new Foo;
console.log( c.constructor === Foo ); // false
console.log( c.constructor === Object ); // true
console.log( c.constructor.prototype ); // {}
That's why you're better off using the new Object.getPrototypeOf
method introduced in ES5.
function Foo() {}
Foo.prototype = {
foo: "bar"
};
var c = new Foo;
console.log( c.constructor === Foo ); // false
console.log( c.constructor === Object ); // true
console.log( c.constructor.prototype ); // {}
console.log( Object.getPrototypeOf(c) ); // { foo: 'bar' }
Another solution would have been to make sure you restore the constructor
reference on the prototype:
function Foo() {}
// Overwriting the initial prototype
Foo.prototype = {
constructor: Foo, // restore the constructor reference
foo: "bar"
};
p.prototype doesn't work because in this case p = someObj.prototype.
Basically when you use the new operator what happen is that the constructor someObj is used to initialize a new object. Which means it returns an object which have the properties and methods of the prototype of the constructor.
Thus p = someObj.prototype and p.prototype is undefined as p is not a constructor.
This article might help explains this more
http://www.htmlgoodies.com/html5/tutorials/javascript-prototypical-inheritance-explained.html#fbid=A2ikc3JLxeD
p
is an instance of someObj
. The prototype belongs to the constructor. You can retrieve p
's constructor prototype using p.constructor.prototype
In Javascript, constructors, and in fact all functions get a prototype property. An objects (that is, a set of key-value pairs), does not have a prototype property. In your example above,
var someObj = function() { } // this is a function, so it has a prototype property
var p = new someObj(); // this is an instance object, so it doesn't
That's why someObj.prototype is defined, but p.prototype is not.