This post is synchronously distributed on my Github

This article will not cover the basics, but rather focus on the various difficulties of prototyping.

Take a closer look at this figure and let’s get to the point

prototype

Let’s start with the Prototype property. This is an explicit stereotype property that only functions have. Almost all functions have this property, with one exception

let fun = Function.prototype.bind()
Copy the code

If you create a function this way, you will notice that the function does not have the prototype attribute.

How did Prototype come into being

This property is created automatically when we declare a function.

function Foo() {}
Copy the code

And the value of this property is an object (that is, a stereotype) with only one property constructor

Constructor corresponds to the constructor, which is Foo.

constructor

Constructor is a public and non-enumerable property. Once we have changed the function’s prototype, the new object does not have this property (which can of course be retrieved from constructor via the prototype chain).

So you must have a question, what is the use of this property? In fact, this attribute can be said to be a legacy of history and is useless in most cases. In my understanding, I think it has two functions:

  • Let the instance object know what function constructed it
  • If you want to add custom methods to the constructors in some libraries, you can do soxx.constructor.methodTo extend the

_proto_

This is an implicit stereotype property for every object, pointing to the stereotype of the constructor that created the object. [[prototype]] is an internal attribute that we can’t access, so use _proto_.

Because there is no concept of class in JS, in order to achieve similar inheritance, through _proto_ object and prototype linked to form prototype chain, so that the object can access the attributes that do not belong to their own.

Instance object_proto_How it came about

As you can see from the figure above, when we use the new operator, the generated instance object has the _proto_ attribute.

function Foo() {}
// This Function is an instance of Function
// function is a syntactic sugar
// Call new Function internally (...)
Copy the code

So it can be said that during the new process, the new object is appended with _proto_ and linked to the prototype of the constructor.

The process of new

  1. The freshman became an object
  2. Link to the prototype
  3. Binding this
  4. Return a new object

All four of these things happen during a call to new, and we can try to implement a new ourselves

function create() {
    // Create an empty object
    let obj = new Object(a)// Get the constructor
    let Con = [].shift.call(arguments)
    // Link to the prototype
	obj.__proto__ = Con.prototype
    // Bind this to the constructor
    let result = Con.apply(obj, arguments)
    // Make sure new comes out as an object
    return typeof result === 'object' ? result : obj
}
Copy the code

For instance objects, both are generated by new, whether function Foo() or let a = {b: 1}.

For creating an object, it is more recommended to create objects in a literal manner. Because you use new Object() to create objects you need to find them layer by layer through the scope chain, but you don’t have this problem with literals.

function Foo() {}
// function is a syntax candy
// Internal equivalent of new Function()
let a = { b: 1 }
// This literal also uses new Object() inside
Copy the code

Function.proto === Function.prototype

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

The answer is definitely no. To illustrate this problem, let’s start with Object.

Object. Prototype is also an Object, but this Object is not created by Object. Instead, the engine creates object.Prototype itself. So it can be said that all instances are objects, but objects are not necessarily instances.

Function.prototype is a special object that, if you print it out in your browser, is actually a Function.

New Function(); Function. Prototype (); new Function(); The answer is no, this function is also created by the engine itself. Prototype is first created by the engine and then function. prototype is created and the two are connected by __proto__. Let fun = function.prototype.bind () has no prototype property. Because function. prototype is an object created by the engine, the engine doesn’t think it needs to add a Prototype attribute to this object.

So again, we can conclude that not all functions arenew Function().

Function(); Function(); Function();

Function.__proto__ === function. prototype [prototype] Function() [prototype] Function() [prototype] Function() Function.__proto__ = Function. Prototype All other constructors can be found in the prototype chain, and Function Function() is essentially a Function. Function. Prototype = function. Prototype = function. Prototype = function. Prototype = function.

conclusion

  • ObjectIs the father of all objects. All objects can pass__proto__To find it
  • FunctionIs the father of all functions, all functions can pass__proto__To find it
  • Function.prototypeObject.prototypeAre two special objects that are created by the engine
  • Except for the above two special objects, all objects are through the constructornewOut of the
  • Function of theprototypeIt’s an object, which is a prototype
  • The object’s__proto__Pointing to the prototype,__proto__The prototype chain is formed by connecting objects and stereotypes