Understand the prototype chain thoroughly

Quote:

Finally understand the prototype in JS, prototype chain.

Now to summarize the rules.

If you understand the diagram, you understand the prototype chain

I couldn’t understand this picture at all before I didn’t understand the prototype chain _ proto _ prototype, but it was only after I understood this picture that I fully understood what the prototype chain was all about.

So if you look at this picture, you have a general idea of the prototype chain.

But you need to know a little bit about this picture before you understand it

JS reference data type

JS is the 7 basic datatype and 1 reference datatype. This reference datatype is Object, which contains (Function, Array, Map, Set, Math….). In a word, reference types are all objects.

Storage of data

Variable values exist in stack space, but the underlying data type and reference data type are somewhat different:

The variable values of the underlying data type reside directly on the stack, but the variable values of the reference data type are references, such as

let number1 = 1;
let func1 = function(){console.log('func1')} 
Copy the code

The number1 variable has a value of 1 and resides directly in the stack space, while func1 receives the address of the anonymous function (the value of func1 is the address of the function).

All functions can be constructors

All constructors mentioned in this article are just concepts linked to new. There is no specified constructor in JS, but the function after new is generally called constructor.

_proto _ and prototype

JS has no real Class. Es6 Class syntax is just syntactic sugar. It is still function and object. Inheritance is very common in life, JS also want to implement this kind of inheritance relationship, so there is _proto _ (prototype chain)

Insert a piece of knowledge unrelated to the main line here: _proto _ is an attribute that the ECMA specification does not want JS users to operate before, so there is an underscore. Later, for some reason, this attribute is recognized and a new method to get prototype Object is created. Object.getprototypeof (). But this method is more recommended.

_proto _ represents the prototype chain, which represents the object pointing that this object inherits. Prototype = proto; prototype = proto;

Let’s start with some code:

function ClassA(value){
	this.Avar = value;
	this.FuncXX = () = >{
	console.log('FuncXX')
	}
}
a1 = new ClassA('a1');
a2 = new ClassA('a2');
console.log(a1._proto_ === ClassA.prototype)
Copy the code

Let’s take a bold assumption: ClassA is a constructor, and this object holds the constructor of this class. Does the new object refer to ClassA? Obviously not. Here a1 and A2 each create a new object space.

So a1 and A2 both instances of _proto _ point to ClassA, right?

Suppose that the two objects that come out of New ClassA have the two properties of ClassA, Avar and FuncXX. Those of you who know execution contexts will know that each call to ClassA creates an execution context, and each time in ClassA the memory of the arrow function is opened and the reference is passed to FuncXX.

In this way, both a1 and A2 objects hold the values of these two attributes. There is no problem with the underlying data type, and different instances can have their own attributes to modify. For functions, instances should operate in the same way in most cases (especially when implementing a function). Prototype: an object that contains attributes that the constructor wants to share.

We set a reference to the object that has the shared property (classa.prototype), and the constructor is usually just the operation that builds the instance. The constructor object and the Prototype object are bound together by default from the function declaration and are usually bidirectional unless you modify the reference yourself.

ClassA is just a constructor, so the proto_ of the instance naturally points to the prototype object.

Here are the structures of the three most important objects to understand in the opening diagram and the prototype chain! :

You can see that there are two more instances that _proto _ points to. The three objects are the constructor object, the constructor prototype object, and the instance object. So let’s talk about what new does.

What did New do

The code:

function ClassA(){
	this.val = 'value';
}
a = new ClassA();

// Here are the functions that simulate the new operation
function new_func(constructor,... args){
    let obj = {};
    let result = constructor.call(obj,args);
    obj._proto_ = constructor.prototype;
    if (typeof result === 'object') {return result;
    }
    return obj;
}
Copy the code

Four steps:

  1. Create the empty object obj
  2. Constructor call (this is assigned to obj)
  3. Sets the stereotype chain, with the instance pointing to the constructor’s stereotype object
  4. Return by case: if the constructor returns an object, return the object directly, otherwise return obj

This makes it clear why the instance proto points to the prototype object.

See figure

There are only two places in the diagram that do not follow the three-object structure, which will be covered below.

Viewed from above:

The first instance of f1, f2, Foo() is an instance of f1, f2, Foo(). Its proto refers to the prototype of the Foo constructor. Constructor — prototype object — instance object.

Next we see two extra arrows: Foo’s prototype object has extra references and Foo’s constructor has extra references.

  1. We’ll start with a reference to the prototype Object that points to the Object constructor. In the connection between the three objects, the instance proto points to the constructor’s prototype, which means that Foo’s prototype is an instance of Object. It’s easy to see how Foo’s prototype object is an object. Here again are the three Object structures of the Object constructor, the prototype Object, instance. In addition to these arrows, the first very special reference appears on Object.prototype: null, the end of the prototype chain.

  2. To return to the Foo constructor reference, we can compare it with the previous paragraph: every instance object has a general object prototype, and constructors should have a general constructor, too. That’s right, the arrow here is the prototype object that points to all the constructors. Function._proto _ === Function. Prototype () {Function._proto _ === Function. Because this is the total constructor, and the total constructor constructs its own constructor, Function is both a constructor and an instance object. Function. Prototype is also an Object, so proto refers to the prototype Object

At this point, the diagram actually covers most of the story, because the other line from O1, O2 (instance of the Object constructor) is the same.

For the most part, an instance of O1 is still a prototype Object that points to Object, and the Object constructor points to the prototype Object of the total constructor.

The diagram is all explained.

To summarize: A stereotype chain is a chain that links all the associated stereotype objects through the instance via the property proto.

Practice: Interview questions

At present, we also need to know a knowledge point, how to find the property of the object

How are properties of objects looked up

Proto (null) returns undefined if the Object has a proto reference. If the Object does not have a proto reference, proto(null) returns undefined if the Object has a proto reference.

// Handwriting simulation
function SearchProp(obj,varString){
    	if (obj == null)
            return undefined;
    	if (obj.hasOwnProperty(varString)){
            return obj.varString;
        }
    return SearchProp(obj._proto_);
}
Copy the code
Look at the topic

one

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

console.log(b.n);
console.log(b.m);

console.log(c.n);
console.log(c.m);
Copy the code

Let’s explain what happened line by line:

  1. The declared anonymous function is assigned to A, and A is now the reference to the function. That is, a.protoType and the A constructor form A bidirectional connection.

  2. Add n attribute n=1 to the prototype object of A

  3. Create instance B, where B and the prototype objects of A and A form A three-object structure

The relationship is as follows:

  1. The prototype property of A points to another object with n and m values

  2. Create instance C, where C’s proto points to A new prototype object

The final relationship is as follows:

Object attribute lookup rule: Start at the end of the prototype chain.

Look at four lines of print:

B.n: The original prototype object from itself to A finds n print 1

B.m: print un______ from itself to A’s original prototype Object to object. ptototype to null

C.n: finds A new prototype object from itself finds n print 2

C.m: found A new prototype object from itself found m print 3

two

var F = function() {};
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

I’m going to draw it right here

I’m not going to analyze the process, but I’m going to look at the print statement

F.a (): from itself to F prototype Object to Object prototype Object finds a function to print a

F.b (): error from self to F prototype Object to Object prototype Object to NULL

F.a(): from itself to the Function prototype Object to the Object prototype Object finds a Function to print a

F.b(): Finds Function B from itself to the Function prototype object to perform printing B

As for the prototype chain question, I think it is very clear to draw the relationship like this. This article will only show these two questions, and the other questions will draw inferential examples.

This article is summed up by oneself, have written wrong place to ask each big guy to carry on correction!

Reference article:

2019 Interview Preparation – JS Prototype and Prototype Chain – Nuggets (juejin. Cn)

In-depth JavaScript Series 6: Prototypes and Prototype Chains – Digging gold (juejin. Cn)