Wow ~ today ushered in the nuggets background writing article new page, do not know this page is to write an article to open, or the new on the ah-ha ah-ha

This origin

In fact, I usually pay great attention to the summary, but generally summary is more casual, will be stored in their own notes software, recommend the use of “language sparrow”, partition directory and page beautiful interaction deep in my heart, of course, suitable for their own notes software is the most important; In the next half month, I will also review the knowledge points I summarized and the difficulties I encountered in the project, and sort them out into nuggets articles

Get into the subject object

Talking about object is actually a very needed concept. There is a very clear word “object-oriented” programming in Java learning in college courses. For object, it is not only to create and inherit, but also some theoretical nouns corresponding to it. These nouns may not be fully reflected in javascript, more reflected in the Java language program;

Introduction to theoretical terms

I suddenly remembered the scene of filling in the concept of college exam paper 🤯🤯🤯

object

The so-called object, essentially refers to things (including people and things) in the form of programming language. Here things can be anything (such as objects that exist objectively, or more abstract concepts); A dog, for example, is understood as an object that has certain specific characteristics (weight, color, name, etc.) and can perform certain actions (bark, eat, sleep, etc.). In javascript, these specific characteristics are properties, and the behaviors that can be performed are methods.

class

A class is a collection of entities that share certain characteristics. It is an abstract data type. It is an abstraction of entities that share the same characteristics. In object-oriented programming languages, a class is an abstraction of the properties and behavior of a class of “things”. For example, “old people”, “children”, “youth” and “middle-aged people” are about the division of people’s age groups. Some of their common characteristics can be divided into “people”.

Figure 1: Relationships between classes

inheritance

In a traditional OOP environment, inheritance usually refers to relationships between classes, but since there are no classes in javascript, its inheritance can only occur between objects; When an object is inherited from another object, new methods are usually added to extend the inherited object. This process is often referred to as “B inherits from A” or “B extends from A”. In addition, for a new object, it can select a few methods from the inherited set and redefine them according to its own needs. Doing so does not change the interface of the object because the method name is the same, but when the new object is called, the method behaves differently

encapsulation

Encapsulation is primarily used to illustrate what is contained in an object. The encapsulation concept usually consists of two parts:

  • Associated data (for storing attributes)
  • What can be done based on this data (methods that can be called)

The purpose of encapsulation is to hide information, that is, the visibility of methods and properties. In general, encapsulating includes encapsulating data and encapsulating implementation. In object systems in many languages, encapsulating data is implemented by syntactic parsing. These languages provide public, private, and protected keywords to limit the visibility of methods and properties. However, javascript does not provide support for these keywords, and can only rely on the scope of variables to implement encapsulation features, and can only simulate public and private encapsulation. With the exception of the lets provided in ECMAScript6, scopes are typically created using functions: typescript is a different story;

polymorphism

The actual meaning of polymorphism is that the same operation on different objects can have different interpretations and different execution results. In other words, when you send the same message to different objects, those objects will give different responses based on that information. Their stay understanding is not deep enough, do not teach fish to swim, direct recommended links to read

Theoretical summary

  • Marry is a student (a student is an object)
  • Marry is a girl, dark hair, tall
  • Method: Marry can study, eat and sleep
  • Class: Marry is an instance of the Person class
  • Prototype object: Marry is a new object extended from the Person object
  • Encapsulation: The Marry object contains data and methods based on that data
  • Inheritance: Marry,xiaoli, and Xiaotong are new objects that extend from the Person object, respectively
  • Polymorphic: You can call the respective talk methods of marry,xiaoli, and Xiaotong at any time, and they all work fine, although these methods produce different results. Marry pays attention to page design, Xiaoli pays attention to page implementation, xiaotong pays attention to page testing

Javascript inheritance implementation

There are many ways to inherit javascript, and there are many common methods in daily use. In many books, there are also methods to introduce inheritance. This article refers to “javascript Advanced Programming (Third Edition)”.

Prototype chain inheritance

In JavaScript we know, the use of the prototype chain is very much, the created object can access the superior object through the prototype chain, and the way of the prototype chain inheritance formally uses this access relationship;

Prototype chain inheritance implementation

    function Super() {
      this.value = true;
    }
    Super.prototype.getValue = function () {
      return this.value;
    }
    function Sub() {}console.log("super".new Super())
    / / Sub super inheritance
    Sub.prototype = new Super();
    // point the sub constructor to sub
    Sub.prototype.constructor = Sub;
    // Create an instance
    var instance = new Sub();
    console.log('sub', instance)

    console.log(instance.getValue())
Copy the code
FIG. 2 Relation of inheritance of prototype chain

The relationship between sub, Super and instance is:

Figure 3. Chain relation of sub and Super inheritance

There are problems with prototype chain inheritance

The main problem with stereotype chains is that stereotype attributes containing reference type values are shared by all instances, which is why you define attributes in constructors rather than in stereotype objects. When inheritance is implemented through a stereotype, the stereotype actually becomes an instance of another type. Thus, the original instance attribute becomes the prototype attribute naturally; Constructors contain reference types

     function Super1() {
      this.colors = ['red'.'blue'.'green'];
    }
    function Sub1() {};//Sub inherits Super
    Sub1.prototype = new Super1();
    var instance1 = new Sub1();
    // View the properties in instance1
    console.log('instance1',instance1)
    instance1.colors.push('black');
    console.log('instance1.colors',instance1.colors);//'red,blue,green,black'
    var instance2 = new Sub1();
    console.log('Instance2 constructed by Sub1',instance2.colors);//'red,blue,green,black'
Copy the code

Figure 4 The parent constructor contains reference types that are modified
  • The stereotype chain inheritance approach, which is a reference relationship for complex data types, is not enjoyed separately in each constructor;
  • Subtypes are created by fighting each other, and arguments cannot be passed to the constructor of the supertype. In many cases, passing argument scenarios is required

Prototype inheritance

Stereotypes allow you to create new objects based on existing objects without having to create custom types. Specific implementation method;

Prototype inheritance implementation

    function object(o) {
      function F() {}; F.prototype = o;return new F();
    }
    var superObj = {
      init: function (value) {
        this.value = value;
      },
      getValue: function () {
        return this.value; }}var subObj = object(superObj);
    console.log('subObj',subObj)
    subObj.init('sub');
    console.log('subObj.getValue',subObj.getValue());//'sub'
Copy the code

The relation with the inheritance of prototype chain; One important difference is that instances of the parent type are no longer prototypes of the child type; This approach is more similar to the implementation of Object.create()

    function Super(){
        this.value = 1;
    }
    Super.prototype.value = 0;
    function Sub(){};

    Sub.prototype = Object.create(Super.prototype);
    Sub.prototype.constructor = Sub;

    // Create instance objects of the subtype
    var instance = new Sub;
    console.log(instance.value);/ / 0
Copy the code
function F(){};
F.prototype = Super.prototype;
Sub.prototype = new F();
Copy the code

As can be seen from the above code, the prototype object of the subclass is an instance object of temporary F, and the prototype object of temporary F points to the prototype object of the parent class. So, in effect, a subclass can inherit properties from its parent class’s prototype, but not from its instance; Both stereotype inheritance and stereotype chain inheritance share values of parent reference types;

View reference type reference issues

 function object(o) {
      function F() {}; F.prototype = o;return new F();
    }
    var superObj = {
      colors: ['red'.'blue'.'green']};var subObj1 = object(superObj);
    subObj1.colors.push("black");

    var subObj2 = object(superObj);
    subObj2.colors.push("white");

    console.log('superObj.colors',superObj.colors);
    console.log('subObj1.colors',subObj1.colors);
Copy the code
Figure 5 stereotype inheritance reference problem

Borrowing constructor

By borrowing constructors, which is pretty straightforward, we actually use the properties of super to call the supertype constructor inside the subtype constructor and execute the constructor on the newly created object by using the apply() and call() methods.

The borrowed construct inherits the implementation

 // Borrow the constructor
    function Super2() {
      console.log("Super2 executed.")
      this.colors = ['red'.'blue'.'green'];
    } 
    function Sub2() {
      // Inherits Super
      Super2.call(this);
    }
    var instance2 = new Sub2();
    instance2.colors.push('black');
    console.log('instance2.colors',instance2.colors);// ['red','blue','green','black']
    var instance3 = new Sub2();
    console.log('instance3.colors',instance3.colors);// ['red','blue','green']
Copy the code
Figure 6 executes by borrowing constructors

The main reason for this is that when we execute in Sub2, the current execution scope of Super2 is in Sub2, forming an internal variable relationship.

The disadvantages of borrowing constructors

  • Super2The method on the prototype is no longer usable
  • Does not serve the purpose of our inheritance

Parasitic combinatorial inheritance

Borrowing constructors can help us solve the object reference problem, stereotype chain inheritance can help us solve the problem of calling stereotype methods, if the two approaches are combined; Constructor inheritance = can get a constructor method, can also break the reference; Combination inheritance, sometimes called pseudo-classical inheritance, refers to an inheritance pattern that combines a chain of archetypes and techniques borrowed from constructors to make the best of the two. The idea behind this is to use stereotype chains to inherit stereotype attributes and methods, while borrowing constructors to inherit instance attributes. In this way, function reuse can be realized by defining methods on the prototype, and each instance can be guaranteed to have its own attributes.

Parasitic combinatorial inheritance implementation

var count = 0; // For counting
    function Super(name) {
      console.log('Super==count',count++)
      this.name = name;
      this.colors = ['red'.'blue'.'green'];
    }
    Super.prototype.sayName = function () {
      console.log('Super==this.name'.this.name);
    };

    function Sub(name, age) {
      console.log('Sub==count',count++) 
      // The second call to Super(), sub.prototype gets the name and colors attributes again and overwrites the values
      Super.call(this, name);
      this.age = age;
    }
    // Inheritance method
    // The first time I call Super(), sub.prototype gets the name and colors attributes
    Sub.prototype = new Super();
    Sub.prototype.constructor = Sub;

    Sub.prototype.sayAge = function () {
      console.log('Sub===this.age'.this.age);
    }
    
    var instance1 = new Sub("bai".29);
    instance1.colors.push("black");
    console.log('instance1.colors',instance1.colors);//['red','blue','green','black']
    instance1.sayName();//"bai"
    instance1.sayAge();/ / 29
    console.log('Super'.new Super())
Copy the code
Figure 7. Parasitic combinatorial relationship

Advantages and disadvantages of parasitic combination

  • advantages
    • Defined in theSuperReference type data is independent in
    • Be able to call the constructorSuperTo pass in a custom parameter
  • disadvantages
    • SuperCall times problem, call once when inheritance, instantiateSubAnd then called againSuper
    • Each instantiationSub“Is calledSuper.call

Parasitic inheritance

The effects of parasitic combinatorial inheritance require two calls to Super. Parasitic combinatorial inheritance is similar to combinatorial inheritance in that it borrows constructors to inherit unshareable properties and inherits methods and shareable properties through a hybrid form of prototype chains. It just takes the form of archetypal inheritance and turns it into parasitic inheritance. Using parasitic combinatorial inheritance, you don’t need to call the parent type’s constructor to specify the stereotype of the subtype. Parasitic inheritance inherits only the stereotype properties of the parent type, while instance properties of the parent type are obtained by borrowing the constructor. That is, we borrow Super’s constructor, but copy Super’s prototype function;

Parasitic inheritance implementation

   function Super(name) {
      console.log("Super === execute")
      this.name = name;
      this.colors = ["red"."blue"."green"];
    }
    Super.prototype.sayName = function () {
      console.log("this.name".this.name)
      return this.name;
    };

    function Sub(name, age) {
      // Borrow the constructor for the first time
      Super.call(this, name);
      this.age = age;
    }
    
    // The method of inheritance is to copy the prototype
    if (!Object.create) {
      Object.create = function (proto) {
        function F() {}; F.prototype = proto;return newF(); }}// Instantiate the super. prototype prototype method to Sub by copying the prototype
    Sub.prototype = Object.create(Super.prototype);
    Sub.prototype.constructor = Sub;

    var instance1 = new Sub("bai".29);
    instance1.colors.push("black");
    console.log('instance1.colors',instance1.colors);//['red','blue','green','black']
    instance1.sayName();//"bai"

    var instance2 = new Super("hu".27);
    console.log("instance2.colors",instance2.colors);//['red','blue','green']
    instance2.sayName();//"hu"
Copy the code
Figure 8. Parasitic prototype inheritance

The chain of these three

Figure 9. Parasitic archetype inheritance

Reference documentation

  • Javascript inheritance idea
  • Javascipt Advanced Programming
  • There are six common ways to inherit JavaScript
  • Unrecorded reference articles

Ps: I sorted it out a long time ago. I checked a lot of documents and blog contents, but I didn’t record them down. I still respect the source of knowledge 🥳🥳