Taha
Taha

Reputation: 451

Function object __proto__ and prototype property

I am trying to figure out the prototype chain of a function that I wrote

function Animal(voice)
 {
  this.voice = voice|| 'meaw'
  }

  Animal.prototype.speak =function() {
  console.log(this.voice);
  }

I know that the Animal function has a prototype property which point to it's prototype object. It's prototype object has constructor which points back and __proto__ property which points to Object object prototype

I am aware that every function object inherits from Function's object prototype and which inherit from Object's object prototype including __proto__ property. Now when I further investigated it, I found out that Function's object prototype and __proto__ property links to the same prototype object.

console.log(Animal.__proto__.constructor.__proto__  == Animal.__proto__.constructor.prototype ); //true
console.log(Animal.__proto__.constructor.__proto__ == Animal.__proto__); //true

Then I did some further test to prove it

Animal.__proto__.constructor.__proto__.test = 28;

console.log(Animal.__proto__.constructor.__proto__.test); // prints 28
console.log(Animal.__proto__.test);  //prints 28

That means it's prototype and the prototype from it is inheriting are same. Any reason why it is set like that?

Upvotes: 2

Views: 908

Answers (4)

nils
nils

Reputation: 27204

Animal is a function and like all functions (unless you modify it), it links back to the Function.prototype object. So:

Animal.__proto__ === Function.prototype //true

Now if we replace Animal.__proto__ with Function.prototype, we get:

Function.prototype.constructor.__proto__ === Function.prototype

Why is that? Function.prototype.constructor links back to its constructor, which is the Function constructor. So this actually means:

Function.__proto__ === Function.prototype

If you're wondering why both Function.__proto__ and Function.prototype share the same value, have a look at the specification.

The Function constructor [[Prototype]] (a.k.a Function.__proto__) is defined as follows in the specification:

The Function constructor is itself a built-in function object. The value of the [[Prototype]] internal slot of the Function constructor is %FunctionPrototype%, the intrinsic Function prototype object (19.2.3).

The Function.prototype property shares the same value:

The value of Function.prototype is %FunctionPrototype%, the intrinsic Function prototype object (19.2.3).

So, since both Function and the result of new Function() are functions, they share the same [[Prototype]]:

var func = new Function()
Function.__proto__ === func.__proto__

Upvotes: 1

Ginden
Ginden

Reputation: 5316

I found out that Function's object prototype and proto property links to the same prototype object.

You are mixing "prototype property" and "prototype object".

.prototype is a property on constructor function. Whenever constructor is called, it creates object with prototype object set to Constructor.prototype.

function Animal(){}
let animal = new Animal();
animal.__proto__ = Animal.prototype;

In fact, __proto__ property is just getter defined on Object.prototype that calls Object.getPrototypeOf.

Your confusion is caused by fact that Object.getPrototypeOf(Animal) === Function.prototype (all functions are instances of Function) and Function constructor/prototype is twisted.

Function.prototype === Function.__proto__; // true
typeof Function.prototype; // "function"

Upvotes: 0

Quarter2Twelve
Quarter2Twelve

Reputation: 613

This is how Javascript lookup chain works.

First note that

Animal.__proto__ === Function.prototype \\true
Animal.__proto__.constructor === Function \\true

Because for any function A,

A.prototype.constructor === A   

Then the question becomes, what is the __proto__ property of Function? It is Function.prototype.

Function.__proto__ === Function.prototype \\true

This is somehow weird because these two properties are not usually the same.

Usually, when a = new A();

a.__proto__ === A.prototype \\true

An instance's __proto__ property equals its constructor's prototype; But consider that every function is the instance of Function and Function itself is a function too. Function is the constructor of itself!

Function.constructor === Function //true

It makes more sense now.


Now we look back at the question.

Animal.__proto__.constructor.__proto__.test = 28;

is equvalent to:

Function.__proto__.test = 28;   

is equvalent to:

Function.prototype.test = 28; 

So it is now clear that the two console.log print out the same because:

Animal.__proto__ === Function.prototype \\ture

As we said at the very beginning.

Upvotes: 1

Bergi
Bergi

Reputation: 664971

You already know that Object.getPrototypeOf(Animal) (or Animal.__proto__) is the Function.prototype object. So let's drop that Animal thing and just repeat your equations with Function.prototype:

Function.prototype.constructor.__proto__ == Function.prototype.constructor.prototype // true
Function.prototype.constructor.__proto__ == Function.prototype // true

Now, the .constructor property of Function.prototype (like for all well-defined prototype objects) points to its respective constructor, the Function constructor function. So we've got

Function.__proto__ == Function.prototype // true
Function.__proto__ == Function.prototype // true

Now, given that Function is a function, it only makes sense that it inherits from Function.prototype like all other functions do.

This is what your testing confirms, as you basically did

Function.__proto__.test = 28;

Function.__proto__.test // 28
Function.prototype.test // 28

And yes, Function.test and Animal.test would yield 28 as well now.

Upvotes: 3

Related Questions