As a front-end developer, we all know that JS is single-inherited, and object.prototype is the top of the prototype chain from which all objects inherit common properties including toString(), valueOf() and so on.

The origin of the chicken and egg problem

First, Object and Function are constructors, and all constructors are instance objects of Function. So Object is an instance of Function; Function. Prototype is an instance of Object. So this raises an interesting chicken-and-egg question:

Object instanceof Function  // true
Function instanceof Object  // true

Object.__proto__ === Function.prototype  // true
Function.__proto__ === Function.prototype  // true
Function.prototype.__proto__ === Object.prototype  // true
Copy the code

Which is the chicken and which is the egg, Object and Function?

Let’s take a closer look at the chicken-and-egg problem caused by this code, starting with the classic prototype/prototype chain diagram below. Prototype: Function Object() : Function Function() : Function Function() : Function Function() : Function Function() : Function Function() : Function Function()

Object.prototype

The end of the prototype chain is Object.prototype (regardless of null). All objects inherit common attributes such as toString() from Object.prototype.

Object. Prototype is not created using the Object function. Look at the following code:

function Dog() {
  this.name = 'trump';
}
var dog = new Dog();
dog.__proto__ === Dog.prototype;  // true
Copy the code

__proto__ points to the constructor’s prototype, that is, dog.__proto__ points to dog. prototype, but object.prototype. __proto__ is null. So Object. Prototype was not created using the Object function, so how was it generated? Object. Prototype is an Object created by the ECMAScript specification at the bottom of the browser, so it looks like Object. Prototype is created by the Object function, but it isn’t.

Function.prototype

Function.prototype and function. __proto__ are the same object.

This also means that Object/Array constructors are essentially the same as Function. They all inherit from Function. Prototype.

Prototype is a Function whose __proto__ attribute points to Object.prototype, which directly inherits root (Object.prototype).

By this we can find out inherit the prototype chain: Function | Object | Array… . — – > the Function prototype — – > Object. The prototype (root). As shown below:

function Object()

When Object is used as a constructor, its __proto__ attribute points to function. prototype:

Object.__proto__ === Function.prototype  // true
Copy the code

From the classic picture:

When o1 is created using new Object(), the __proto__ attribute of o1 points to the constructor’s prototype attribute. O1.__proto__ === Object.prototype returns true.

Function. Prototype points to an Object whose __proto__ points to object. prototype. Since Function. Prototype points to an ordinary Object created by Object, it follows the basic rules.

function Function()

Function is a Function object with a __proto__ attribute. Function is a Function object with a __proto__ attribute. Function is a Function object with a __proto__ attribute.

Function.__proto__ === Function.prototype  // true
Copy the code

This is a bit of a brain burn, let’s look at the chicken born eggs born chicken problem.

Function & Object chicken and egg problem

The Object constructor inherits from function. prototype, and the Function constructor inherits from Object.prototype. Why does this happen? You must first understand the function. prototype Object a little more deeply, because that is what causes both Function instanceof Object and Object instanceof Function to be true.

// Object instanceof Function
Object.__proto__ === Function.prototype   // true

// Function instanceof Object
Function.__proto__.__proto__ === Object.prototype   // true

// Object instanceof Object
Object.__proto__.__proto__ === Object.prototype   // true

// Function instanceof Function
Function.__proto__ === Function.prototype   // true
Copy the code

Prototype = Function. Prototype = Function. Prototype = Function.

  1. Function.prototypeIt can be called like a normal function, but always returnsundefined.
  2. Ordinary functions are actuallyFunctionThat is, ordinary functions inherit fromFunction.prototype. namelyfunc.__proto__ === Function.prototype.
  3. Function.prototypeInheritance inObject.prototypeAnd noprototypeThis property.
  4. So,Function.prototypeIt’s actually a different function, independent of PIFunctionIs generated.

Function. __proto__ is Function. Prototype.

Prototype; Function. Prototype; Function and Object and other constructors;

I’m probably tired of seeing this, too. Is it still a bit confusing? Chaos is normal. In the next installment, we’ll ask another old friend to help us straighten it out once and for all. That old friend is Instanceof.

If you find this article helpful, please feel free to like and follow my GitHub blog. Thank you very much!