Prototype and prototype chain

  • JavaScript is a literal script language, a dynamically typed, weakly typed, prototype-based language.

  • JavaScript is almost unique among all languages, perhaps the only one that can be called “object-oriented,”

  • JavaScript is one of the few languages that can create objects directly because there are no classes at all.

  • In JavaScript, a class cannot describe what an object can do (because there are no classes), and an object can directly define its own behavior.

JavaScript only has objects.

  • Every object initializes a property inside it, called prototype, when we access an object’s property

  • If the object doesn’t have the property, it will look for the property in Prototype, which will have its own prototype, and so on and so on

  • Relationship: the instance. The constructor. The prototype = instance. __proto__

  • Features:

    • JavaScriptObjects are passed by reference, and each new object entity we create does not have a copy of its own prototype. When we modify the stereotype, the objects associated with it inherit the change
  • When we need a property, the Javascript engine looks first to see if the property is present in the current object, and if it isn’t

  • It looks up whether its Prototype Object has this property, and so on, until it reaches the Object built-in Object

  • Prototype:

    • JavaScriptContains one of all objects in the[__proto__]Internal property, which corresponds to the prototype of the object
    • JavaScript function objects, except for prototypes[__proto__]In addition, it’s presetprototypeattribute
    • When a function object is created as a constructor, the prototype property value is used as the prototype of the instance object[__proto__].
  • The prototype chain:

    • When an object calls a property/method that does not exist by itself, it will destroy itself[__proto__]Associated predecessorsprototypeObject to find
    • If they don’t, they go to theprototypeThe prototype[__proto__]Associated predecessorsprototypeTo try to find. And so on until you find a property/method orundefinedSo far. And that creates what’s called the prototype chain.
  • Prototype features:

    • JavaScriptObjects are passed by reference, and when you modify a stereotype, the objects associated with it inherit the change

We divide objects in JS into ordinary objects and function objects

Attribute: Prototype

Every Function object (except function.prototype) has a prototype property (this property refers to an object, the prototype object)

Prototype is a default property of a function that is automatically added by the JS compiler during function creation

var fn1 = function (){ }; var fn2 = new Function(); function fn3(){ }; console.log(fn1.prototype); console.log(fn2.prototype); console.log(fn3.prototype); // prototype {// Function. Prototype {// Function. Prototype {// Function. Look at the code: console.log(number.prototype); console.log(String.prototype); console.log(Function.prototype); console.log(Function.prototype.prototype); // The result is as follows: [] ()! [] ()Copy the code

You can see the built-in constructors Number, String, and so on, whose prototypes point to a normal object (Number{} and String{}).

Function () {[native code]}; Function () {[native code]};

This Function object (function. prototype) has no prototype property, so its prototype returns undefined.

function Cat(){}; Cat.prototype.name = 'prototype '; // Add cat.prototype. color = 'black'; Cat.prototype.sayHello = function (){console.log(' Hello, my name is +this.name '); } var cat1 = new Cat(); Var obj = Cat. Prototype; // Prototype object console.log(obj); console.log(cat1.constructor); console.log(obj.constructor); console.log(Cat.prototype === cat1.constructor.prototype);Copy the code

Attribute: constructor

Each object has a hidden attribute constructor that points to the object’s constructor (” class “)

From the above code we can see that the instance object cat1 and the prototype object obj both have the same constructor, pointing to Cat!

Let’s write it another way:

Function Cat(){} Cat. Prototype = {// prototype: 'black', 'black', sayHello: Function (){console.log(' hello, my name is +this.name '); } } var cat1 = new Cat();Copy the code

It’s a little bit more intuitive to see what the prototype object is, but

console.log(Cat.prototype === cat1.constructor.prototype); 

console.log(Cat.prototype.constructor === Object);  console.log(cat1.constructor === Object); 

The constructor of cat1 points to the root constructor Object. The constructor of cat1 points to the root constructor Object.

The attribute constructor is not reliable!

So, what’s a prototype for?

The main purpose of archetypes is to "inherit"

var Person = function(name){

   this.name = name;

};

Person.prototype.type = 'human';

Person.prototype.getName = function(){

   console.log(this.name);

}

var p1 = new Person('jack');

var p2 = new Person('lucy');

p1.getName();

console.log(p1.type);

p2.getName();

console.log(p2.type); 

Copy the code

In the example, you add attribute methods to the person.prototype object

So the ordinary object from the Person instance (p1, p2) inherits the property method (Type getName)

Object.prototype.jdk = 'abc123'; Prototype. SayHi = function () {alert(' hello '); }; String.prototype.pin = function () { console.log(this + '&biubiu'); } var str = 'yoyo'; var num = 123; Var arr = [1, 2, 3]; var boo = true; str.sayHi(); Num. SayHi (); Arr. SayHi (); Boo.sayhi (); // Console. log(str.jdk); // abc123 console.log(num.jdk); // abc123 console.log(arr.jdk); // abc123 console.log(boo.jdk); // abc123 str.pin(); // yoyo&biubiu num.pin(); Num. Pin is not a function arr.pin(); Arr. Pin is not a function boo.pin(); // Boo. pin is not a functionCopy the code

Do you see anything?

All objects inherit property methods from the Object.prototype (in other words, they are all instances of Object).

STR also inherits property methods from the String.prototype prototype

Look again at the example I wrote earlier:

Date. Prototype. GetWeek = function () {var arr = [' Sunday ', 'on Monday, Tuesday, Wednesday,' ', 'on Thursday, Friday,' Saturday]; var index = this.getDay(); //0-6 return arr[index]; } var dates = new Date(); console.log(dates.getWeek()); // 'Monday'Copy the code

All Date objects will inherit the getWeek method

How does that happen? We’re going to talk about the prototype chain, right

** Attribute: _ _ proto _ (prototype) **

Each object has a hidden attribute _proto _ that points to obj1.__proto __ -> Person.prototype of the constructor that created it

Meng force… What is another prototype??

Prototype is for every function object; this _ _ proto _ _ is for every object

Attribute _ _ proto _ _ unofficial standard attribute, but the mainstream browsers basically support

var n = 123;
var s = 'jdk';
var b = true;
var a = [];
var f = function (){};
var o = {};

console.log(n.__proto__);
console.log(n.__proto__ === Number.prototype);
console.log(s.__proto__ === String.prototype);
console.log(a.__proto__ === Array.prototype);
console.log(f.__proto__ === Function.prototype);
console.log(o.__proto__ === Object.prototype);
console.log(b.__proto__ === Boolean.prototype);
Copy the code

Objects point to prototype objects through _ _ proto _ _ and function objects point to prototype objects through prototype

What about the prototype chain? Where’s the chain?

Using the example above, let’s look for the prototype chain:

Object.prototype.jdk = 'abc123'; Object.prototype.sayHi = function (){console.log(' hello! '); } var str = 'yoyo'; str.sayHi(); // Console. log(str.jdk); // 'abc123'Copy the code

How does STR access the sayHi method and JDK properties?

Take a look at the hasOwnProperty() method, which determines whether an attribute is a member of the object itself

Take a look at the general process:

console.log(str.hasOwnProperty('sayHi')); //false STR has no sayHi method of its own

console.log(str.__proto__.hasOwnProperty('sayHi')); // False prototype objects also have no sayHi method

console.log(str.__proto__.__proto__.hasOwnProperty('sayHi')); // The true prototype has the sayHi method

STR -> str._ _ proto _ _ -> str._ _ proto _ _.

Let’s describe the implementation:

Str.sayhi () –> no sayHi method –> No sayHi method –> No sayHi method –> No sayHi method –> No sayHi method –> No sayHi method –> No sayHi method –> No sayHi method –> No sayHi method –> No sayHi method –> No sayHi method –> No sayHi method –> No sayHi method –> No sayHi method –> No sayHi method –> No sayHi method — String.prototype._ _ proto _ _ –> Point to object. prototype –> Find sayHi method –> Execute sayHi method

Is it like a chain? This is what we call the prototype chain

The prototype chain is maintained by _ proto _ _!

The following example is more graphic:

The prototype chain ends with null

If not, congratulations, you seem to have grasped some philosophy of life:

“The Book of Changes” — “Tai Chi gives birth to two instruments, two instruments give birth to four images, and four images give birth to eight diagrams”

Tao Te Ching — “No, the beginning of name and heaven”

Is not familiar, is not very unexpected!

In short, the stereotype chain, if the current object does not have the property itself, looks up the level of the prototype object, all the way to the outermost layer, which is NULL

The instanceof operator is used to check whether the constructor’s prototype property appears on the prototype chain of an instance object

Now that we’re familiar with stereotypes and stereotype chains, let’s take a look at the common ways in which javascript implements “inheritance” :

This (bind, call, apply) function Cat(n,c){this.name = n; // This (bind, call, apply) function Cat(n,c){this.name = n; this.color = c; This. Trait = function (){console.log(' console.log '); }} cat.prototype. skill = function (){console.log(' catch rat '); } function Dog(n,c,f){// this. Food = f; Cat.call(this,n,c); Var dog1 = new Dog(' yellow','shi'); var dog1 = new Dog(' yellow','shi'); // Instance object console.log(dog1.name); / / two ha dog1. Trait (); / / show MOE dog1. Skill (); // Error dog1. Skill is not a functionCopy the code

We see limitations in this method of inheritance. Attribute methods on the “superclass” prototype cannot be inherited, so Erha does not have the ability to catch mice

Function Cat(n,c){this.name = n; this.color = c; This. Trait = function (){console.log(' console.log '); }} cat.prototype. skill = function (){console.log(' catch rat '); } function Dog(n,c,f){this.food = f; } Dog.prototype = new Cat(); Var dog1 = new Dog(' yellow','shi'); console.log(dog1.name); // undefined console.log(dog1.food); // shi dog1.trait(); // skill(); Console. log(dog1.constructor); // CatCopy the code

Problem a:

When instantiating an object, the “parent class” cannot be passed as a parameter. As a result, there is no value for accessing dog1.name

Problem two:

(4) Now dog1. Constructor points to Cat. It’s obviously not ethical or environmentally friendly…

Function Cat(n,c){this.name = n; this.color = c; This. Trait = function (){console.log(' console.log '); }} Cat. Prototype. Skill = function (){console.log(); } function Dog(n,c,f){ this.food = f; Cat.call(this,n,c); } // Dog. Prototype = new Cat(); Dog.prototype = object.create (cat.prototype); / / Prototype chain inheritance / / Object. The create () is used to create an empty Object, and the Object of the [[Prototype]] to link to the Prototype t Prototype. The constructor = Dog; Var dog1=new Dog(' yellow','shi'); console.log(dog1.name); / / 2, the console. The log (dog1. Food); // shi dog1.trait(); // skill(); Console. log(dog1.constructor); // DogCopy the code

The combination of these two approaches can achieve relatively perfect inheritance.

Don’t forget to correct the constructor (type).

Var parentObj = {name: 'xm', age: 25, friends: ['xw', 'xh', 'xz'], showName: ['xw', 'xh', 'xz'] function(){ alert(this.name); Var childObj = {}; var childObj = {}; For (var I in parentObj){childObj[I] = parentObj[I]; } // parentObj.friends.push('xf'); console.log(childObj); console.log(parentObj);Copy the code

Question:

If the inherited member is of a reference type, then the member of that reference type is shared between the parent object and the child object, meaning that the modification affects both the parent object and the child object. Deep copy required!

Summary:

In JavaScript, there are no classes, only objects

For years JS developers have tried to mimic class-oriented as much as possible (copying into something that looks like “class”)

The prototype mechanism is different from the “class” mechanism. In class-oriented languages, it is possible to make multiple copies of a class (i.e., “instances”), but in JavaScript, no such copying takes place

The prototype mechanism is an internal chaining mechanism, whose essence is to delegate behavior and create links between objects

This chaining is enforced when a property/method reference is made to an object and no such property/method exists

In this case, the [[Prototype]] link tells the engine to look for the property/method on the linked object

Then, if the object does not satisfy the query, its [[Prototype]] will be looked up again, and so on…

This series of links between objects forms what is called a primitive chain.

Each object that inherits a child function of the parent function contains an internal attribute _ _ proto _ _, which contains a pointer to the parent function’s prototype. If the parent function’s prototype object’s _ _ proto _ _ _ attribute is the prototype of the function at the next level, the prototype chain is formed in this process.

Diagrams between objects: