Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript prototype through Object.create()

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?

like image 784
Taha Ahmad Avatar asked Apr 26 '12 08:04

Taha Ahmad


4 Answers

The 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:

  1. Get the f object.
  2. Does f have its own property called "answer"?
  3. No, does f have a prototype?
  4. Yes, does the prototype have its own property called "answer"?
  5. 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.

like image 90
T.J. Crowder Avatar answered Oct 27 '22 10:10

T.J. Crowder


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"
};
like image 42
Ionuț G. Stan Avatar answered Oct 27 '22 10:10

Ionuț G. Stan


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

like image 32
GillesC Avatar answered Oct 27 '22 09:10

GillesC


p is an instance of someObj. The prototype belongs to the constructor. You can retrieve p's constructor prototype using p.constructor.prototype

like image 25
KooiInc Avatar answered Oct 27 '22 10:10

KooiInc