Five ways to implement inheritance in js

Five ways to implement inheritance in js

Borrowing Constructors

The basic idea of ​​this technique is simple: call the supertype constructor from within the subtype constructor. Also, a function is nothing more than an object that executes code in a specific environment, so by using the apply() and call() methods you can also execute the constructor on a newly created object.

function Box(name){
 this.name = name
}
Box.prototype.age = 18

function Desk(name){
 Box.call(this, name) // Object impersonation, object impersonation can only inherit information in the constructor}

var desk = new Desk('ccc')
console.log(desk.name) // --> ccc
console.log(desk.age) // --> undefined

From this we can see that only instance properties are inherited, and the properties on the prototype are inaccessible. This pattern solves two problems: it allows parameter passing and inheritance, but without a prototype, it cannot be reused.

Composition inheritance

function Box(name){
 this.name = name
}
Box.prototype.run = function (){
 console.log(this.name + 'Running...')
}

function Desk(name){
 Box.call(this, name) // object impersonation}

Desk.prototype = new Box() // prototype chain var desk = new Desk('ccc')
console.log(desk.name) // --> ccc
desk.run() // --> ccc is running...

The idea behind this inheritance method is to use the prototype chain to inherit prototype properties and methods, and to use the constructor to inherit instance properties.

Prototypal inheritance

Prototype inheritance: Prototypes can be used to create new objects based on existing objects without having to create custom types. Speaking of this, we must mention a person. Douglas Crockford gave a method in an article he wrote in 2006, "Prototype inheritance in Javascript":

function object(o) { // pass a literal function function F(){} // create a constructor F.prototype = o; // assign the literal function to the prototype of the constructor return new F() // finally return the instantiated constructor }

Consider the following example:

function obj(o) {
 function F (){}
 F.prototype = o;
 return new F()
}

var box = {
 name: 'ccc',
 age: 18,
 family: ['brother','sister']
}

var box1 = obj(box)
console.log(box1.name) // --> ccc
box1.family.push('sister')
console.log(box1.family) // --> ["brother", "sister", "sister"]

var box2 = obj(box)
console.log(box2.family) // --> ["brother", "sister", "sister"]

Because the implementation logic of the above code is very similar to prototype chain inheritance, the reference array, that is, the family attribute, is shared.

Parasitic inheritance

function obj(o) {
 function F (){}
 F.prototype = o;
 return new F()
}
function create(o){
 var clone = obj(o) // Create a new object by calling a function clone.sayName = function(){ // Enhance this object in some way console.log('hi')
 }
 return clone // Return this object }

var person = {
 name: 'ccc',
 friends: ['aa','bb']
}

var anotherPerson = create(person)
anotherPerson.sayName() // --> hi

The code in this example returns a new object, anotherPerson, based on person. The new object not only has all the properties and methods of person, but also has its own sayHi() method. Parasitic inheritance is also a useful pattern in situations where you are primarily concerned with objects rather than custom types and constructors. Using parasitic inheritance to add functions to objects will reduce efficiency due to the inability to reuse functions, which is similar to the constructor pattern.

Parasitic Combinatorial Inheritance

As mentioned earlier, composite inheritance is the most commonly used inheritance mode in JavaScript, but it also has its own shortcomings. The biggest problem with composite inheritance is that no matter what the circumstances, the supertype constructor is called twice: once when creating the subtype prototype, and once inside the subtype constructor. Yes, the subtype will eventually contain all the instance properties of the supertype object, but we have to rewrite these properties when calling the subtype constructor. Let's take a look at the following example:

function SuperType(name){
 this.name = name;
 this.colors = ['red','black']
}
SuperType.prototype.sayName = function (){
 console.log(this.name)
}
function SubType(name, age){
 SuperType.call(this, name) // Second call to SuperType
 this.age = age
}

SubType.prototype = new SuperType() // First call to SuperType
SubType.prototype.constructor = SubType
SubType.prototype.sayAge = function (){
 console.log(this.age)
}

The first time the SuperType constructor is called, SubType.prototype gets two properties: name and colors. They are all instance properties of SuperType, but now they are located in the prototype of SubType. When the SubType constructor is called, the SuperType constructor is called again, which again creates the instance attributes name and colors on the new object. Therefore, these two properties mask the two properties with the same name in the prototype. That is, there are two sets of name and colors attributes: one on the instance, and one on the prototype. This is the result of calling the SuperType constructor twice. The solution to this problem is parasitic combination inheritance.
The so-called parasitic combinatorial inheritance is to inherit properties by borrowing constructors and to inherit methods through a hybrid form of prototype chains. The basic idea behind this is that there is no need to call the supertype's constructor in order to prototype a subtype; all we need is a copy of the supertype's prototype. Essentially, you use parasitic inheritance to inherit from the supertype's prototype and then assign the result to the subtype's prototype. The basic pattern of parasitic composite inheritance is as follows:

function object(o) {
 function F (){}
 F.prototype = o;
 return new F()
}
function inheritPtototype(subType, superType){
 var prototype = object(superType.prototype) // create object prototype.constructor = subType // enhance object subType.prototype = prototype // specify object }

function SuperType(name){
 this.name = name
 this.colors = ['red', 'white']
}

SuperType.prototype.sayName = function(){
 console.log(this.name)
}

function SubType(name,age){
 SuperType.call(this,name)
 this.age = age
}

inheritPtototype(SubType, SuperType)

SubType.prototype.sayAge = function(){
 console.log(this.age)
}

var instance = new SubType('ccc', 18)

instance.sayName() // --> ccc
instance.sayAge() // --> 18
console.log(instance)

The structure printed out by the console:

Detailed diagram:

The efficiency of this example is that it only calls the SuperType constructor once, and thus avoids creating unnecessary, redundant properties on SubType.prototype. At the same time, the prototype chain remains unchanged; therefore, instanceof and isPrototypeOf() can still be used normally. This is also the inheritance method used by many large companies.

The above are the details of the five methods of implementing inheritance in js. For more information about js inheritance, please pay attention to other related articles on 123WORDPRESS.COM!

You may also be interested in:
  • Detailed explanation of native Javascript inheritance methods and their advantages and disadvantages
  • Several ways to implement inheritance in JavaScript
  • JS inheritance implementation method and advantages and disadvantages detailed explanation
  • JavaScript class inheritance multiple implementation methods
  • JavaScript uses the prototype property to implement inheritance operations example
  • How to implement inheritance using JavaScript

<<:  Linux file systems explained: ext4 and beyond

>>:  What is table partitioning and partitioning? MySql database partitioning and table partitioning method

Recommend

Sublime Text - Recommended method for setting browser shortcut keys

It is common to view code effects in different br...

About the location of the H1 tag in XHTML

There has been a lot of discussion about H1 recent...

Share 5 helpful CSS selectors to enrich your CSS experience

With a lot of CSS experience as a web designer, we...

Linux checkup, understand your Linux status (network IO, disk, CPU, memory)

Table of contents 1. Core commands 2. Common comm...

A brief analysis of the function calling process under the ARM architecture

Table of contents 1. Background knowledge 1. Intr...

Limit input type (multiple methods)

1. Only Chinese characters can be input and pasted...

How to solve the error of connecting to the database when ServerManager starts

Servermanager startup connection database error R...

Docker swarm simple tutorial

swarm three virtual machines 132,133,134 1. Initi...

An example of elegant writing of judgment in JavaScript

Table of contents Preface 1. Monadic Judgment 1.1...

Introduction to Linux File Compression and Packaging

1. Introduction to compression and packaging Comm...

How to implement the King of Glory matching personnel loading page with CSS3

Those who have played King of Glory should be fam...

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

Detailed explanation of the misplacement of the in...

Neon light effects implemented with pure CSS3

This is the effect to be achieved: You can see th...

A brief discussion of four commonly used storage engines in MySQL

Introduction to four commonly used MySQL engines ...