1. Where does constructor point to on the prototype object

Each function has a Prototype property, which is a reference to the function’s prototype object. Each prototype object has a constructor property, which points to the function object itself.

Verify:

  function Fun(params) {}
  console.log(Fun.prototype.constructor==Fun)//true
  var a=new Fun();
  console.log(a.__proto__.constructor===Fun)//true
Copy the code

2. Display versus implicit archetypes

First, we need to understand what the stereotype object does: it defines properties and methods shared by all object instances.

  • Each function has a prototype explicit property, which is just a reference to the prototype object

  • Each instance object has a __proto__, called an implicit prototype, which is also a reference. Eventually, it also points to the prototype object

The implicit prototype on the instance object has the same value as the prototype constructor corresponding to the instance; that is, the two different reference variable attributes point to the same block of address. All point to the prototype object

That is, in the chestnut below: the console outputs true

  function Fun(params) {}var a=new Fun();
  console.log(a.__proto__===Fun.prototype)
Copy the code

We can think of it as theta

  • This statement is executed on new:this.__proto__=Fun.prototype

It looks like this in memory:

3. Talk about prototypes and prototype chains

All the following concepts are my own understanding, if there is any mistake, please point out.

Prototype: Every function in JavaScript has a prototype property that holds a reference to an empty Object in memory. This Object is the function’s prototype Object and is used to share properties and variables. How to share? And that’s definitely using the concept of instance objects, where we instantiate this function, which in this case is also called a constructor, we instantiate multiple instance objects, so that all of our instances have access to properties or variables on our prototype object.

The first thing to know is two concepts: implicit prototype and __proto__. Implicit stereotypes are properties of instance objects, whereas explicit stereotypes are properties of functions. But the same thing is that they’re all a reference, and they don’t all point to the same block of memory, which is our prototype object.

Prototype Chains: Why are prototype chains called prototype chains? Simply because it is executed in a chained order of calls. In one sentence, it’s essentially looking for properties or methods along the implicit stereotype, so it’s also called the implicit stereotype chain. When we use an instance method to execute a property or method, we now assume that the desired property and method are in the prototype object. The order of execution in JavaScript memory is to look for the property or method in the prototype object via the __proto__ reference of the current instance. If the method does not have the property or method we are looking for, we continue in the __proto__ property of the current prototype Object into the memory referenced by __prote__, which is the prototype Object of the Object function (because we said earlier, The prototype property of each function refers to an empty Object instance, so there must be a __proto__ reference to the Object prototype. If it’s still not there, do some error handling. Because __proto__ is null in the prototype Object to which object. prototy points.

Next we can write some code to analyze its in-memory state:

function Fn() {
    this.test1=function(){
      console.log('test()')
    }
    Fn.prototype.test2=function(){
      console.log('test2()')}}let fn=new Fn();
  fn.test1();
  fn.test2();
  console.log(fn.toString())
  console.log(fn.test3)
Copy the code

The graph in memory looks something like this

  • fn.test1()The instance object has this method, so execute it directly
  • fn.test2(), first look in the sample object, find no, and then pass__proto__This property is found in the prototype object. perform
  • fn.toString(), according to the previous step, find the prototype object found does not have this property, then in__proto__To find, find, and execute a prototype object
  • fn.test3After finding the prototype Object of Object, and finding that there is still no Object, enter the implicit prototype of Object, where it has reached the end, soundefined

There are actually two things we can take note of:

  • **Object prototype objects are not Object sample objects: ** Display prototypes of functions default to point to instance objects of one Object at a time. One special exception, however, is the instance Object to which the Prototype property of Object itself points, because its implicit Prototype property points to NULL.
  • At the end of the prototype chain is the prototype Object of Object, because its implicit prototype is NULL

4. Relationship between Function, Object and prototype

Function is a relatively special Function because all functions are examples of Function, so the implicit prototype for each Function points to the prototype object of the Function.

The picture below is a very classic one. From the picture, we can see the following points:

  • All functions have two properties, explicit stereotypes (a sample Object pointing to Object) and implicit stereotypes (a prototype Object for Function).

  • Function is actually instantiating itself, so its implicit stereotype is executed, and therefore has its implicit stereotype equal to its explicit stereotype (this is a special case)

  • The Object Function is an example of Function, so we have object.__proto__ in the figure pointing to the example of function.protype. In fact, we can see this result because all functions are examples of Function, and Object is no exception

5. The prototype chain points to the topic

Now that you’ve seen this, why don’t you do some problems:

p.__proto__  // Person.prototype
Person.prototype.__proto__  // Object.prototype
p.__proto__.__proto__ //Object.prototype
p.__proto__.constructor.prototype.__proto__ // Object.prototype
Person.prototype.constructor.prototype.__proto__ // Object.prototype
p.__proto__.constructor // Person
Person.prototype.constructor  // Person
Copy the code

6. Explore instanceOf

A instance B

First, let’s be clear about what instance does: Return true if B’s explicit prototype object is on A’s prototype chain

Interviewer: Write an instanceof by hand, young man!

Ok!

  function instancof(left, right) {
    let leftp = left.__proto__;// Get the left implicit prototype
    let rightp = right.prototype;// Get a reference to right's explicit prototype object
    // The search is over
    while (true) {
      if (leftp == null) {
        false
      }
      if (leftp == rightp) {
        return
        true
      }
      leftp = leftp.__proto__
    }
  }
Copy the code

Writing an instance by hand is not difficult. Here are some questions to stimulate you:

  console.log(Object instanceof Function)//true
  console.log(Object instanceof Object)//true
  console.log(Function instanceof Function)//true
  console.log(Function instanceof Object)//true
  function Foo(params) {}console.log(Object instanceof Foo);//false
Copy the code

Remember that the principle of instance is to determine whether the prototype of a function object is in the prototype chain of the previous example object, so we can easily write the principle and the result.

7. Two interview questions

The first line:

  function A() {}
  A.prototype.n=1;
  var b=new A();
  A.prototype={
    n:2.m:3
  }
  var c=new A();
  console.log(b.n,b.m,c.n,c.m)
Copy the code

Instantiate the object by placing an n attribute on the object. Instantiate the object with an n attribute. Next, A creates A new prototype object for its function object, assigns two properties and instantiates it. This instantiation refers to the prototype object, so our two sample objects refer to two different prototype objects

So the output is:

1 undefined 2 3
Copy the code

The second way:

function F() {}Object.prototype.a = function () {
    console.log('a')}Function.prototype.b = function () {
    console.log('b')}var f = new F();
  f.a();
  f.b();
  F.a();
  F.b();
Copy the code

ToString (); toString(); toString(); toString(); The second one adds a method to Function’s prototype object

F (): f (): f (): f (): f (): f (): f (): f (): f (); Function.prototype.__proto__-> object.prototype.a () F.b(): function.prototype.__proto__ -> object.prototype.a () F.b(): Each Function is an instance object of Function, so F as an instance object has its own prototype chain, and its implicit prototype points to the prototype object that Function’s display prototype points to