A few important concepts

Prototype object constructor (instance is a normal object) prototypeObject (prototype object) If there is a mistake, also hope to point out in time, thank you!Copy the code

Constructor/prototype and __proto__

Every object has a __proto__, whereas prototype is only available for function objectsCopy the code

First, Obj.__proto__ is called Obj
A prototype object \color{red}{prototype object}
Prototype called fn
A prototype object \color{red}{prototype object}
This prototype object contains all shared properties and methods.

  1. Sometimes the current object doesn’t have a method that we want to use, so we want to see if it has a prototype, how do we get the prototype of the current object?

Here’s an example:

function Person(name){ this.name = name; } var p1 = new Person(' Person '); console.log(p1.__proto__); //Person.prototype console.log(p1.__proto__ === Person.prototype); //trueCopy the code

In everyday business we often need to manipulate function object prototypes, but we rarely need to manipulate ordinary objects, so we often see prototype in some code and __proto__ is rarely seen

Note: Every object has a __proto__, while prototype only has a function objectCopy the code

2. As shown in the figure, we see a familiar constructor on the console. What is it?

Constructor is enclosed in braces {}, indicating that it is an attribute in the stereotype object.

What does this property do? Take a look at the following code

The following writing with the Person. The prototype. The constructor intuitively use mathematical thinking to understand: who write on both sides of the equal sign are the same

console.log(p1.__proto__.constructor ); //Person
Copy the code

That is, the prototype object has a property called constructor that points to its own constructor, which is called the prototype \color{red}{prototype} prototype of the current object P1.

That is, the prototype object has a constructor pointer, which always points to the current object’s prototype (constructor).

Therefore, the constructor attribute is commonly used to get the prototype of the current object.

What’s going on? Aren’t there multiple ways to get constructors? Nice!

As follows:

P1. The constructor = = = p1. __proto__. Constructor p1. The constructor = = = Person. The prototype. The constructor using mathematical thinking about replacement, ask each other, is possibleCopy the code

The object p1 is an instance of Person, and since it comes from Person new and Person is its constructor, its constructor points to Person;

Prototype is an object whose constructor points to a Person. Prototype is an instance of Person.

In fact, it’s really understandable. I looked up a lot of information, and although it’s fake, most people on the Internet think it’s easier to understand the prototype and the prototype chain

Halftime summary:

  1. __proto__ is used to retrieve the prototype object, all the way down the hierarchy, __proto__ until the result is null. To go through this process is to go through the prototype chain of your current object. (More on this later)

  2. Get the prototype (constructor) of the current object using constructor

  3. Any object has a prototype, any object can be a prototype of another object, so what is a prototype? What is a prototype object?

Popular understanding —-

Both tigers and cats belong to the feline family, that is, both tigers and cats are new instances of the feline family, which is the original tiger and cat.

The prototype property is an object with attributes and methods that both tigers and cats have inherited, such as color, climbing and jumping, etc. We often say: look for the prototype of a method that can’t be found at the moment, which is actually looking for the prototype object.

To sum up —-

A prototype is a constructor for the current object. It has a Prototype property on it. The prototype property is an object that contains methods and properties that can be inherited by all descendants.

To avoid confusion, the rest of this article will focus on prototype objects, which I prefer to call constructors. (So far, the relationship between the prototype and the prototype object has been clarified, if you do not understand, please leave a message)

  1. In actual code, these three attributes will be used for inheritance, and there is a pit like this:

Function Person(name) {this.name = name} function() {this.name = name) {this.name = name} console.log(p.__proto__ === Person.prototype) // true console.log(p.__proto__ === p.constructor.prototype) // true // Person. Prototype = {getName: Function () {}} var p = new Person(' proto__ ') console.log(p.__proto__ === Person. Prototype) // true console.log(p.__proto__) === p.constructor.prototype) // false why false????Copy the code

GetName: function(){}} {constructor points to the root constructor Object

So at this point, p.constructor === Object is true, its constructor is now a constructor called Object, not a constructor called Person, how do you make them equal? This succession is doomed to failure

So what do we do? … class = ‘class.php’ >… class = ‘class.php’ >… class = ‘class.php’ >…

Person.prototype = { getName: function() {} } var p = new Person('jack') p.constructor = Person; // This is the line, the core! console.log(p.__proto__ === Person.prototype) // true console.log(p.__proto__ === p.constructor.prototype) // trueCopy the code

Prototype chain

In the last section, __proto__ can get the prototype object, go up to get the whole chain, how to get it? I don’t know. Let’s just look at the code:

var function Person(name){ this.name = name; } var p1 = new Person(' Person '); // Do you know what will be printed if you do not print it? 1. P1. __proto__? 2. Person. __proto__?Copy the code
  1. Person. Prototype
  2. Prototype the Person constructor (‘ Person ‘, ‘Person’, ‘Person’, ‘Function’, ‘prototype’)

Just keep this picture in your head while we analyze question 2:

p1.__proto__ ? Person.prototype
p1.__proto__.__proto__?
Copy the code
  1. P1__proto__ is Person. Prototype
  2. Person. Prototype: __proto__
  3. Prototype is an Object, so you should be able to think of it in seconds: Object.prototype

To sum up, problem 2 asks for the prototype object of p1’s constructor. Here are the answers:

Person. The prototype. __proto__? Prototype: p1.__proto__. Constructor.__proto__? Object.prototype p1.__proto__.constructor.prototype.__proto__ ? Object.prototype Person.prototype.constructor.prototype.__proto__ ? Object. The prototype dizzy? , please turn to the above two constructor equation about replacement: p1. __proto__. The constructor is Person to Person. The prototype. The constructor is the Person understand? Hey hey ~Copy the code

Now that we’re done with problem 2, let’s see how we can solve for the chain.

The purpose of going back to the prototype chain is to find some method or attribute that meets the current coding needs, so —

  1. First, find p1’s parent, that is, its constructor Person, and all properties and methods are fixed in prototype. We click on the prototype object to search:
Get Person. Prototype from p1.__proto__, find that the constructor Person collection does not have what we wantCopy the code
  1. The Person collection doesn’t have one, so we’ll have to look higher, still using __proto__, the only way to get to the prototype collection with one click
Function. Prototype (Person.__proto__)Copy the code
  1. Further up:
Function.__proto__ gets Object. Prototype, and finds that the constructor Object collection is still missingCopy the code
  1. Don’t give up, keep going back, persistence is victory:
Get null from Object.__proto__, Nani ????Copy the code

After 18 generations of searching and finding anthropoids, there is still no method or attribute we are looking for. There is only one explanation: the guy you are looking for is not born yet.

If you force this method or use this property, you will get a string of red characters: ‘XXX is undefined…..’ ‘

The above is the process of tracing the prototype chain in line with the original intention of solving practical needs.

For example, p1’s family cultivates its own unique unique knowledge from generation to generation, and then passes it on to its offspring. Finally, P1 inherits the unique knowledge (attributes and methods) of all the ancestors above.

In the JS world, we are scattered objects, there is always a mechanism to connect them to run to work to produce, so THE JS author designed this set of inheritance mechanism, which is the so-called prototype chain.

You can see here, that you are a studious and diligent students, to give you a lovely encouragement ~

But we’re still going to have to continue with this smelly, long foot-binding

Console. log(p1.arguments) // arguments from where? Console.log (person.call (window)) // Where does the call method come from?Copy the code

I’m sure you’ve seen a lot of code where arguments pop up and you can’t find where arguments are declared all over the world. After all, p1 doesn’t have the arguments attribute. Find its prototype Person and it doesn’t have one on it either.

According to the above analysis, had to go back to print rummage, sure enough —

The console. The log () Function. The prototype / / Function () {} (an empty Function) console. The log (Object. GetOwnPropertyNames (Function. The prototype)); / * output [" length ", "name", "the arguments," "caller", "constructor", "bind", "toString," "call", "apply"] * /Copy the code

Object: getOwnPropertyNames () {getOwnPropertyNames (); getOwnPropertyNames (); getOwnPropertyNames (); It has many methods and properties.

But! Prototype is an empty Function. Why? Look at the next section

3. Special citizens

The __proto__ of all Function objects refers to function. prototype, which means that it is the prototype of all Function objects and that it is an Empty Function.

Regardless of whether it’s an empty function or not, take a look at the following prototypes of various constructors in the JS world and you’ll be surprised that they are all the same:

Number.__proto__ === Function.prototype // true Number.constructor == Function //true Boolean.__proto__ === Function.prototype // true Boolean.constructor == Function //true String.__proto__ === Function.prototype // true Constructor == Function //true // all the constructors come from function.prototype, Prototype // true object. constructor == Function // true // All constructors come from function.prototype, Function.__proto__ === function. prototype //true function. constructor == Function //true Array.__proto__ === Function.prototype // true Array.constructor == Function //true RegExp.__proto__ === Function.prototype // true RegExp.constructor == Function //true Error.__proto__ === Function.prototype // true Error.constructor == Function //true Date.__proto__ === Function.prototype // true Date.constructor == Function //trueCopy the code

There are 12 build-in constructors/objects in JavaScript (JSON is new in ES5), and eight of them are listed here. The rest such as Global are not directly accessible and Arguments are only created by the JS engine during function calls; There is also Math, JSON exists as an Object, no need for new, Object __proto__ is object.prototype.

The following

Math.__proto__ === Object.prototype  // true
Math.construrctor == Object // true
 
JSON.__proto__ === Object.prototype  // true
JSON.construrctor == Object //true
Copy the code

Function objects mentioned above include custom ones, of course. The following

Function Person() {} var Perosn = function() {} console.log(person.__proto__ === function.prototype) //  true console.log(Man.__proto__ === Function.prototype) // trueCopy the code

This print shows that all constructors come from function. prototype, even the root constructor Object and Function itself. So all constructors inherit function. prototype properties and methods. Therefore, functions are the only type whose Typeof results in function.

Function. Prototype is a null Function. Not only that, but if you take the prototype of the Array constructor, it’s also an empty Array:

Console. log(array.prototype) // Function () {} (null Function) console.log(array.prototype) // [] (null Array)Copy the code

How to do? Do it again! It didn’t. It must have had ducks!

/ / Function. The first prototype/Array. The prototype is an Object the console. The log (Function. The prototype. __proto__ = = = Object. The prototype) / / true Console. log(array.prototype. __proto__ === object.prototype) //true //Object.prototype Null, end of world console.log(object.prototype. __proto__ === null)//trueCopy the code

End of the world? The prototype of the object should be function. Because all object prototypes point to their constructor’s Prototype property.

And if so, what would it look like? Please look at:

If object.prototype. __proto__ === Function. Prototype is true, Function.prototype.__proto__ === object.prototype __proto__ === object. prototype.........Copy the code

A loop? This chain never ends, okay? ????? And it doesn’t make much sense!

So the designer makes Object.prototype point to null and the chain ends happily.

4. Soul interview questions

function Person(name) { this.name = name } var p2 = new Person('king'); Emphasis: The prototype object is a property of the constructor, ====> constructor (); constructor (); Prototype console.log(p2.__proto__)//Person. Prototype console.log(p2.__proto__.__proto__) Person.prototype's __proto__, which is itself an object, so here's the output: Object. Prototype console.log(p2.__proto__.__proto__.__proto__) Null console. The log (p2. __proto__. __proto__. __proto__. __proto__)/behind/null, An error console. The log (p2. __proto__. __proto__. __proto__. __proto__. __proto__)/behind/null, Error console.log(p2.constructor)//Person console.log(p2.constructor)//Person console.log(p2.prototype) Constructor)//Function an empty Function without the prototype attribute Console. The log (Person. The prototype) / / print out the Person. All the methods and properties in the prototype this object the console. The log (Person) prototype) constructor) / / Person Console. log(person.prototype. __proto__)//Person.prototype is the object, so output: Object.prototype console.log(Person.__proto__)//Function.prototype console.log(Function.prototype.__proto__)//Object.prototype console.log(Function.__proto__)//Function.prototype console.log(Object.__proto__)//Function.prototype console.log(Object.prototype.__proto__)//nullCopy the code