JavaScript Composition and Inheritance Explained

JavaScript Composition and Inheritance Explained

1. Introduction

Before learning inheritance, you need to have a certain understanding of the prototype chain.

If you don’t understand, you can read another article of mine first, which has a more detailed explanation of the prototype chain: Detailed Explanation of JavaScript Prototype Chain.

If you already understand, please continue.

I wrote a blog post before that listed all the inheritance methods, but I found it too long to read it all at once, and it is not conducive to absorbing knowledge, so I will separate the composite inheritance part first, and then make up the parasitic part later.

2. Prototype chain inheritance

The parent class instance is used as the prototype of the child class. The implicit prototype __proto__ of the two instances created by the child class points to the instance of the parent class, and the implicit prototype __proto__ of the parent class instance points to the prototype of the parent class father.prototype
According to the characteristics of the prototype chain, all subclass instances can inherit the properties of the parent class prototype.

Read the following picture to understand the code clearly:

 //Father class function father() {
      this.fatherAttr = ["fatherAttr"];
    }
    
    //Properties on the prototype of the parent class father.prototype.checkProto = "checkProto";

    //Subclass function child() {}

    // Use the father instance as the prototype of the child constructor child.prototype = new father();
    child.prototype.constructor = child;

    //Two subclass instances const test1 = new child();
    const test2 = new child();

    console.log("Test 1:");
    console.log("test1:", test1);
    console.log("test2:", test2);
    console.log("test1.fatherAttr:", test1.fatherAttr);
    console.log("test2.fatherAttr:", test2.fatherAttr);

    console.log("Test 2:");
    test1.fatherAttr.push("newAttr");
    console.log("test1.fatherAttr:", test1.fatherAttr);
    console.log("test2.fatherAttr:", test2.fatherAttr);

    console.log("Test 3:");
    console.log("test1.checkProto:", test1.checkProto);

Features:

  • Neither of the two instance objects has a fatherAttr attribute, but because the instance of the parent class has the fatherAttr attribute, and now the instance of the parent class serves as the prototype of the child, according to the prototype chain, they can share the attributes on the prototype of their own constructor child . (Test 1)
  • Because there is only one instance of the parent class as their prototype, all instances share a property fatherAttr on the prototype. When the property on the prototype is a reference type, here it is an array, adding a new content to test1 will cause fatherAttr on test2 to change as well. (Test 2) (Disadvantages)
  • child constructor cannot pass input parameters. (shortcoming)
  • Instances can access the properties on the parent class prototype, so reusable methods can be defined on the parent class prototype. (Test 3)

3. Constructor inheritance

Bind this on the parent class to the child class, that is, when the child class creates an instance, the parent class's constructor will be called inside the child class, and the properties on the parent class will be copied to the child class instance, so the instance will inherit these properties.

    //Father class function father(params) {
      this.fatherAttr = ["fatherAttr"];
      this.params = params;
    }

    //Properties on the prototype of the parent class father.prototype.checkProto = "checkProto";

    //Subclass function child(params) {
      father.call(this, params);
    }

    //Two subclass instances const test1 = new child("params1");
    const test2 = new child("params2");

    console.log("Test 1:");
    console.log("test1:", test1);
    console.log("test2:", test2);
    console.log("test1.fatherAttr:", test1.fatherAttr);
    console.log("test2.fatherAttr:", test2.fatherAttr);

    console.log("Test 2:");
    test1.fatherAttr.push("newAttr");
    console.log("test1.fatherAttr:", test1.fatherAttr);
    console.log("test2.fatherAttr:", test2.fatherAttr);
    
    console.log("Test 3:");
    console.log("test1.checkProto:", test1.checkProto);

Features:

  • Both instance objects have the copied fatherAttr attribute, so there is no shared attribute. To create an instance, all attributes of the parent class must be copied once. And because the parent class prototype cannot be inherited, the methods cannot be reused and are forced to copy the methods. (Test 1) (Disadvantages)
  • Adding a new content test1 only changes the properties of test1 itself and will not affect test2 . (Test 2)
  • child constructor can pass parameters to customize its own properties. (Test 1)
  • Instances cannot inherit properties from the prototype of their parent class. (Test 3) ( Disadvantages )

4. Combination inheritance

Combining prototype chain inheritance and constructor inheritance, you can use them according to the characteristics of the two inheritances.

  //Father class function father(params) {
      this.fatherAttr = ["fatherAttr"];
      this.params = params;
    }

    //Properties on the prototype of the parent class father.prototype.checkProto = "checkProto";

    //Subclass function child(params) {
      //The second call to the parent class constructor father.call(this, params);
    }

    // Use the father instance as the prototype of the child constructor child.prototype = new father(); //The parent class constructor is called for the first time child.prototype.constructor = child;

    //Two instances const test1 = new child("params1"); //Jump from here to the subclass constructor and call the parent class constructor for the second time const test2 = new child("params2");

    console.log("Test 1:");
    console.log("test1:", test1);
    console.log("test2:", test2);
    console.log("test1.fatherAttr:", test1.fatherAttr);
    console.log("test2.fatherAttr:", test2.fatherAttr);

    console.log("Test 2:");
    test1.fatherAttr.push("newAttr");
    console.log("test1.fatherAttr:", test1.fatherAttr);
    console.log("test2.fatherAttr:", test2.fatherAttr);

    console.log("Test 3:");
    console.log("test1.checkProto:", test1.checkProto);

    console.log("Test 4:");
    delete test1.fatherAttr
    console.log("test1:", test1);
    console.log("test1.fatherAttr:", test1.fatherAttr);

Features:

  • Both instance objects have the copied fatherAttr attribute. To create an instance, all attributes of the parent class must be copied once (constructor inheritance characteristics, test 1), but the parent class prototype can be accessed, and the reuse method can be defined on the parent class prototype. (Prototype chain inheritance features, test 1)
  • Adding new content test1 only changes the properties of test1 itself and does not affect test2. (Constructor inheritance features, test 2)
  • child constructor can pass parameters to customize its own properties. (Constructor inheritance features, test 1)
  • Instances can inherit properties from the prototype of their parent class. (Prototype chain inheritance features, test 3)
  • The parent class constructor is called twice, two instances are generated, the subclass prototype chain is created once, and when the subclass is used to create an instance, it is called once inside the subclass, and the second time covers the first time. (shortcoming)
  • Because the parent class constructor is called twice, if delete is used to delete the fatherAttr attribute copied from the instance, the instance still has fatherAttr attribute on the parent class instance pointed to by the implicit prototype. (Prototype chain inheritance features, test 4) (Disadvantages)

This is the end of this article on the detailed explanation of JavaScript combination and inheritance. For more relevant JavaScript combination and inheritance content, please search for previous articles on 123WORDPRESS.COM or continue to browse the related articles below. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • New ideas for time formatting in JavaScript toLocaleString()
  • isPrototypeOf Function in JavaScript
  • Detailed explanation of JavaScript prototype chain
  • Detailed explanation of js event delegation
  • nuxt.js multiple environment variable configuration
  • Differences and usage examples of for, for...in, for...of and forEach in JS
  • Javascript uses the integrity attribute for security verification

<<:  How to build sonarqube using docker

>>:  Some findings and thoughts about iframe

Recommend

MySQL trigger simple usage example

This article uses examples to illustrate the simp...

Installation steps of mysql under linux

1. Download the mysql tar file: https://dev.mysql...

CSS to achieve zoom in and out close button (example code)

This effect is most common on our browser page. L...

Importance of background color declaration when writing styles

As the title says, otherwise when the page is revi...

Specific use of Node.js package manager npm

Table of contents Purpose npm init and package.js...

Detailed explanation on how to modify the default port of nginx

First find out where the configuration file is wh...

Detailed explanation of nginx's default_server definition and matching rules

The default_server directive of nginx can define ...

Steps to build the vite+vue3+element-plus project

Use vite to build a vue3 project You can quickly ...

Differences between Windows Server 2008R2, 2012, 2016, and 2019

Table of contents Common version introduction Com...

Solution to input cursor misalignment in Chrome, Firefox, and IE

Detailed explanation of the misplacement of the in...

How to draw a mind map in a mini program

Table of contents What is a mind map? How to draw...

A detailed introduction to Linux file permissions

The excellence of Linux lies in its multi-user, m...

25 div+css programming tips and tricks

1. The ul tag has a padding value by default in M...

How to achieve seamless token refresh

Table of contents 1. Demand Method 1 Method 2 Met...