Charlie
Charlie

Reputation: 23858

Object.prototype and Function.prototype

In JS functions are said to be objects. Now when functions are tested against objects, they behave differently.

a = {};
console.log(a.prototype);   //undefined

function myFunc() {};
console.log(myFunc.prototype); //Object
Object.getPrototypeOf(myFunc); //function(){}

And to make things worst, an example in this MDN article seem to change the constructor of a function prototype.

secondConstructor.prototype.constructor = secondConstructor;

Can someone please explain this behaviour?

Upvotes: 0

Views: 115

Answers (2)

Max Koretskyi
Max Koretskyi

Reputation: 105547

What leads to a common confusion is that a function as an object has .__proto__ property and as a function has .prototype property. They have different meaning.

Most JavaScript objects have a prototype object, that can be accessed using Object.getPrototypeOf() method, or simply .__proto__ property. This is the object which is used to reuse code and is consulted when a property accessor can't find requested property on an object, then it's looked up on its prototype. This is how common methods like .apply are available on a function. This is how you access this object in your example:

Object.getPrototypeOf(myFunc); //function(){}

Only functions have .prototype property, which is used by new operator when a new object is created using the function. When a function is called with new operator and a new object is created, JS checks the .prototype property of the function. If it points to an object, JS sets this object as a prototype of a newly created object. That's why the .prototype of an object in your example is undefined:

a = {};
console.log(a.prototype); // undefined

Can someone please explain this behaviour?

secondConstructor.prototype.constructor = secondConstructor;

The constructor property of an object usually points at the function that was used to create the object. When a function is declared, this property is created automatically on the object that .prototype property of the function points to.

function c() {}
c.prototype.constructor === c; // true
var o = new c();
o.constructor === c; // true

However, this property can easily be changed:

c.prototype = {constructor: function notCAnymore() {}}
var o = new c();
o.constructor === c; // false

Now we don't have a reference to the correct function anymore. So after changing the prototype, we may need to restore the .constructor property:

c.prototype = {constructor: function notCAnymore() {}}
c.prototype.constructor = c; // restoring the correct constructor
var o = new c();
o.constructor === c; // true

And that is exactly what is done in the example. The prototype is changed:

secondConstructor.prototype = new firstConstructor;

If object is created now the pointer to a correct constructor is lost:

var o = new secondConstructor();
o.constructor === secondConstructor; // false

That's why they use this code to restore it:

secondConstructor.prototype.constructor = secondConstructor;
var o = new secondConstructor();
o.constructor === secondConstructor; // true

Upvotes: 4

Geeky
Geeky

Reputation: 7496

For your first statement

var a = {};
console.log(typeof(a));
console.log(Object.getPrototypeOf(a));

Here a, is just an object ,when you check its type it just returns object and you cannot access its prototype

All JavaScript objects inherit the properties and methods from their prototype.

Objects created using an object literal, or with new Object(), inherit from a prototype called Object.prototype

Here in the first case, a is just object literal so its prototype is empty.

In the second case, myFunc is a definition which objects can be created through new ,but it is also an object,so thats the reason the prototype is object here

The Object.getPrototypeOf() method returns the prototype (i.e. the value of the internal [[Prototype]] property) of the specified object.

For MyFunc the prototype is function because it has been defined as function

function myFunc() {};
console.log(myFunc.prototype); //Object
console.log(Object.getPrototypeOf(myFunc));

In the third snippet,It is the case of inheritance

function parent(name){
this.name=name;
}

function child(childname){
this.childname=childname;
}

child.prototype=Object.create(parent.prototype);

console.log(parent.prototype);
console.log(parent.prototype.constructor);
console.log(child.prototype);
console.log(child.prototype.constructor);

When child is inherting parent,its prototype and constructor is parent,in order to change the constructor to be of the same MDN has mentioned it as

child.prototype.constructor=parent;

Hope it helps

Upvotes: 1

Related Questions