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:
JavaScript
Objects 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:
JavaScript
Contains 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 presetprototype
attribute - 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 predecessorsprototype
Object to find - If they don’t, they go to the
prototype
The prototype[__proto__]
Associated predecessorsprototype
To try to find. And so on until you find a property/method orundefined
So far. And that creates what’s called the prototype chain.
- When an object calls a property/method that does not exist by itself, it will destroy itself
-
Prototype features:
JavaScript
Objects 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: