Inheritance of Object-Oriented Programming II

Inheritance of Object-Oriented Programming II

The sun is shining today, and the cloudy day turns to sunny. My mood has been cloudy since the sunny day. Why is this because I found my grandfather.... Duck eggs are not bad for the classic quotes on money, I still enter the venue with a cheerful sentence. I have been talking about object-oriented in these two chapters, and I don t know what it is facing. In the end, you can only face yourself without facing the object. Hahaha, although in reality you may not be able to grasp the goal around you, but The objects in js can be grasped as long as you want. This is definitely not a loss in this wave of steadily and steadily. Passing through the west wind and mountains and rivers, you will know sweetness and happiness. After all, this is the world of learning. There are only future dreams and the person you want to be, as well as poetry and the distance. Today, let s talk about inheritance in object-oriented. I don t know why js inherits from objects. Shouldn t it be inherited from daddy, hahaha, let s just code it first, or that sentence, I m a rookie. Hope the big guys squirt lightly.

inherit

Everyone should know that the most talked-about thing in the OO language is inheritance, right? Let's argue if you don't agree, hahaha, then let's take a look at how js implements inheritance today?

  1. Prototype chain

    • Prototype chain

      Briefly review the relationship between constructor, prototype, and instance: every constructor has a prototype object, the prototype object contains a pointer to the constructor, and the instance contains an internal pointer to the prototype object. If the prototype object is equal to an instance of another type, then the prototype object will contain a pointer to another prototype, and the corresponding other prototype also contains a pointer to another constructor. If another prototype is an instance of another type, then the above relationship still holds. That's fun, it's like you let one snake bite another snake's tail, and the next one bites the other's tail..., then this becomes the prototype chain. Take a look at the code and pictures first, after all, oppoR50000s makes your thinking clearer hahaha.

      function SuperType () { this .property = true ; } SuperType.prototype.getSuperValue = function () { return this .property } function SubType () { this .subproperty = false } //Inherited SuperType SubType.prototype = new SuperType(); SubType.prototype .getSuperValue = function () { return this .subproperty; } var instance = new SubType(); alert (instance.getSuperValue()); //true Copy code

      It should be noted that the instance.constructor at this time now points to the SuperType, this is because the constructor in the original SubType.prototype has been rewritten.

      Calling instance.getSuperValue() will go through three search steps: 1) search for an instance; 2) search for SubType.prototype; 3) search for SuperType.prototype, and find the method in the last step. Just look up one by one.

    • Default prototype

      Don't forget that all our reference types inherit Object. When using all reference types, there are not generally tostring methods and valueOf methods. Where do they come from? They can't be the same as Monkey King, right? Oh no, isn't it born out of thin air that was conceived by a fairy stone, right? ? Hahaha, right? They all come through inheritance. This inheritance is also achieved through the prototype chain, so remember that the default prototype of all functions is an instance of Object, so the default prototype will contain an internal pointer to Object.prototype. This is also the fundamental reason why all custom types inherit tostring() and valueOf().

    • Determine the relationship between prototype and strength

      How to determine the relationship between the prototype and the instance, we have also seen the prototype chain above, what a messy relationship, then there must be a way to determine the relationship between the instance and the prototype

      • instanceof can test the constructor function that has appeared in the prototype chain of the instance, and the result will return true. Due to the relationship of the prototype chain, we can say that instance is an instance of any type of Object, SuperType or SubType

        ALRT (instance the instanceof Object ); //to true ALRT (instance the instanceof Supertype); //to true ALRT (instance the instanceof the SubType); //to true copy the code
      • The isPrototypeOf() method, the same as long as the prototype appears in the prototype chain, it can be said to be the prototype of the instance derived from the prototype chain

        ALRT ( Object .prototype.isPrototypeOf (instance)); //to true ALRT (SuperType.prototype.isPrototypeOf (instance)); //to true ALRT (SubType.prototype.isPrototypeOf (instance)); //to true copy the code
    • Define methods carefully

      Sometimes a subtype needs to override a method in the supertype, or need to add a method that does not exist in the supertype. But no matter what, the code to add a method to the prototype must be placed after the statement that replaces the prototype

      function SuperType () { this .property = true } SuperType.prototype.getSuperValue = function () { return this .property; } SubType.prototype = new SuperType(); //Add a new method SubType.prototype.getSubValue = function () { return this .subproperty; } //Override the method in the supertype SubType.prototype.getSuperValue = function () { return false }; var instance = new SubType(); ALRT (instance.getSuperValue ()); //to false copy the code

      *Note: *When inheriting through the prototype chain, you cannot use object arguments (rewritten) to create prototype methods. Because this rewrites the prototype chain, the prototype chain will be cut off, and there is no relationship between the two classes.

    • Prototype chain problem

      • Although the prototype chain is very powerful and can be used to implement inheritance, it also has problems. How can it be better if there is no problem? right? The most important thing is to eat too much. Hahaha, kidding, the main problem is that the prototype attribute containing the reference value will be shared by all instances; a prototype in the prototype chain becomes an instance of another type, so it is logical The properties of the current prototype are realized

        function SuperType () { this .colors = [ "red" , "blue" , "green" ]; } function SubType () { } SubType.prototype = new SuperType(); var instance1 = new SubType(); instance1.colors.push( "black" ); alrt(instance1.colors); //red,blue,green, black var instacne2 = new Subtype(); ALRT (instance2.colors); //Red, Blue, Green, Black copy the code
      • When creating an instance of a subtype, you cannot pass parameters to the supertype's constructor. In fact, it should be said that there is no way to pass parameters to the superclass without affecting all object instances.

  2. Borrow constructor

    • The main idea of this technique is very simple, which is to call the supertype constructor inside the subtype constructor. A function is just an object that executes code in a specific environment, so by using the apply() and call() methods, you can also execute the constructor on the newly created object (in the future). The code borrows the supertype constructor through call The () method (or apply() method can also be used) actually calls the SuperType constructor in the instance environment of the newly created SubType. In this way, all the object initialization codes defined in the SuperType() function are executed on the new SubType object

      function SuperType () { this .colors= [ "red" , "blue" , "green" ]; } function SubType () { SuperType.call( this ); } var instance1 = new SubType(); instance1.colors.push( "black" ); alrt(instance1.colors); //red,blue,green, black var instacne2 = new Subtype(); ALRT (instance2.colors); //Red, Blue, Green copy the code
    • Pass parameters

      Compared with the prototype chain, borrowing the constructor has a great advantage, that is, you can pass parameters to the supertype constructor in the subtype constructor.

      function SuperType ( name ) { this .name = name; } function SubType () { //Inherited SuperType, and also passed the parameters SuperType.call( this , "Nicholas" ); //instance attribute this .age = 29 ; } var instance = new SubType(); ALRT (instance.name); //"Nicholas" ALRT (instance.age); //29 copy the code
    • Problems with this model

      The problem of this mode is actually the same as that of the constructor. The methods are defined in the constructor, so function reuse is impossible to talk about, because every time a new instance is performed, it is equivalent to a copy of the constructor. If there are more methods, the memory will be quite large.

  3. Combinatorial inheritance

    • It's here, it's here, it's here with a trick, combinatorial inheritance is currently the most commonly used inheritance method, which refers to the combination of the prototype chain and the technology of borrowing constructors. The idea is to use the prototype chain to realize the inheritance of prototype properties and methods, and to realize the inheritance of instance properties by borrowing the constructor. This not only achieves function reuse by defining methods on the prototype, but also ensures that each instance has its own properties.

      function SuperType ( name ) { this .name = name; this .colors = [ "red" , "blue" , "green" ]; } SuperType.protptype.sayName = function () { alrt( this .name) }; function SubType ( name,age ) { //inherited properties SuperType.call( this ,name); this .age =age; } //Inheritance method SubType.prototype = new SuperType(); SubType.prototype.constructor =SubType; SubType.prototype.sayAge = function () { alrt( this .age); } var instance1 = new SubType( "Nicholas" , 29 ); instance1.colors.push( "black" ); alrt(instance1.colors); //red,blue,green, black instance1.sayName(); //Nicholas instance1.sayAge(); //29 var instance2 = new SubType( "Greg" , 27 ); ALRT (instance2.colors); //Red, Blue, Green instance2.sayName (); //Greg instance2.sayAge (); //27 copy the code
  4. Prototype inheritance

    • Wrap an object with a function, and then return the call of this function. This function becomes an instance or object that can add properties at will. object.create() is this principle.

      var person = { name : "Nicholas" , friends :[ "Shelby" , "Court" , "Vant" ] } function object ( obj ) { function F () {} F.prototype=obj; return new F(); } var sup1=object(person); copy code
    • Advantages: similar to copying an object, using functions to wrap it.

    • Disadvantages: 1. All instances will inherit the properties on the prototype. 2. Unable to achieve reuse. (The attributes of the new instance are all added later)

  5. Parasitic inheritance

    • Put a shell on the prototype inheritance.

      function object ( obj ) { function F () {}; F.prototype = obj; //inherited the passed parameters return new F(); //return function object } var sup1=object(person); //The above is prototypal inheritance, pass parameters to prototypal inheritance in Tao Ge shell function subobject ( obj ) { var sub = object(obj); sub.sayHi = function () { alrt( "hi" ); } return sub } var SUP2 = subobject.txt (Person); duplicated code
    • Advantages: No custom type is created, because it just sets a shell to return the object, this function naturally creates a new object

    • Disadvantages: prototypes are not used and cannot be reused

  6. Parasitic combined inheritance

    • I said that combinatorial inheritance is the most commonly used inheritance mode in javascript, but it also has its shortcomings. After all, no one is perfect, right? The biggest problem with combinatorial inheritance is that no matter what the situation is, the supertype constructor will be called twice: in order when the subtype prototype is created, and the other time in the subtype constructor. The result is that there are two groups of constructors. A set of name and colors attributes is in the prototype of SubType.

      function SuperType ( name ) { this .name =name; this .colors =[ "red" , "blue" , "green" ] } SuperType.prototype.sayName = function () { alrt( this .name) } function SubType ( name,age ) { SuperType.call( this ,name); //The second call to SuperType() this .age = age } SubType.prototype = new SuperType(); //first call SubType.protptype.construtor = SubType; SubType.protptype.sayAge = function () { alrt( this .age); } Copy code

    • Parasitic combined inheritance is here: inherit properties by borrowing constructors, and inherit methods through the hybrid form of the prototype chain. The basic idea is: you don t have to call the supertype s constructor in order to specify the subtype s prototype. All we need is a copy of the supertype s prototype. Essentially, it uses parasitic inheritance to inherit the supertype s prototype. Assign the result to the prototype of the subtype

      function inheritPrototype ( subType,superType ) { var prototype = object(superType.prototype);//create object prototype.constructor = subType;//enhance object subType.prototype = prototype; //specify object } Copy code

      Inside the function, the first step is to create a copy of the supertype prototype, the second step is to add the constructor attribute to the created copy, so as to make up for the loss of the default construtor attribute due to rewriting the prototype, and the last step is to create the object (copy) , Assigned to the prototype of the subtype.

    There were a lot of things this week. While waiting for the interface to be done in the background, I quickly finished writing the unfinished stuff. The interface boss is still sleeping, and we dare not bother hahaha, seriously and counseled, and finally got the js object. Although it feels very obscure and difficult to understand, I still gnawed this hard bone. The knowledge afterwards should be smooth and smooth. I think too much hahaha, how can it be so easy to think of messy knowledge points, anyway, anyway , And it s over.