This article looks at how class inheritance is implemented in JavaScript and compares the differences.
What is inheritance
Inheritance, in which a subclass inherits the characteristics and behavior of its parent class, makes its objects have the instance fields and methods of the parent class. Inheritance is an integral part of object-oriented programming.
1.1 the advantages
Reduce code redundancy
A parent class can provide generic attributes to a child class without having to change the attributes of each child class to add functionalityCode reuse
Same as aboveThe code is easy to manage and expand
Subclasses can implement their own unique functions based on the parent class
1.2 disadvantages
High coupling
If you modify the parent code, it affects all subclasses that inherit from itAffect performance
Subclasses inherit from the data members of the parent class, some of which are useless. However, at instantiation time, memory is already allocated. Therefore, the program performance is affected to a certain extent.
Second, the example
Take books in a library for example. Here is the simplified parent class Book (also known as the base class). The goal is to produce a Computer subclass by inheriting from the parent class. Also, the subclass has a new method, say, that prints its own title.
function Book(){
this.name = ' '; / / title
this.page = 0; / / number of pages
this.classify = ' '; / / type
}
Book.prototype = {
constructor: Book,
init: function(option){
this.name = option.name || ' ';
this.page = option.page || 0;
this.classify = option.classify || ' ';
},
getName: function(){
console.log(this.name);
},
getPage: function(){
console.log(this.page);
},
getClassify: function(){
console.log(this.classify); }};Copy the code
Next, we will explain the realization and optimization methods of several inheritance methods in subclass Computer. Start racing
Instance inheritance
function Computer(){
Book.apply(this.arguments);
}
Computer.prototype = new Book();
Computer.prototype.constructor = Computer;
Computer.prototype.init = function(option){
option.classify = 'computer';
Book.prototype.init.call(this, option);
};
Computer.prototype.say = function(){
console.log('I\'m '+ this.name);
}
Copy the code
3.1 Call the parent class constructor for initialization
function Computer(){
Book.apply(this.arguments);
}
Copy the code
The constructor of the Computer calls the parent class’s constructor to initialize the Computer. Causes a subclass to have the same initialization properties as its parent.
3.2 Pass the stereotype of the parent class to the child class
Computer.prototype = new Book(); Instantiate the superclass Book using the new operator and assign the instance object to the prototype of the subclass. In this way, subclass Computer can access the attributes of the parent class through the prototype chain.
3.3 disadvantages
- The parent class
Book
The constructor of “is executed twice- Once in
Computer
Constructor ofBook.apply(this, arguments);
- Once in
Computer.prototype = new Book();
In this mode, there is a certain performance waste.
- Once in
- The parent class instantiation could not pass parameters
Computer.prototype = new Book();
, this instantiation method, can not makeBook
The parent class receives an unfixed set of arguments.
Iv. Inheritance of the original type
function Computer(){
Book.apply(this.arguments);
}
Computer.prototype = Object.create(Book.prototype);
Computer.prototype.constructor = Computer;
Computer.prototype.init = function(option){
option.classify = 'computer';
Book.prototype.init(option);
};
Computer.prototype.say = function(){
console.log('I\'m '+ this.name);
}
Copy the code
The improvement here is object.create (book.prototype). This returns a new object inherited from the prototype object Book.prototype. And the properties under this object have been initialized. Creating a new Object with Object.create does not call the Book constructor. This way, inheritance can also be implemented through a chain of prototypes.
5. Object. Create is compatible with simple versions
Object. Create is not supported by older browsers. So here is a brief introduction of compatible versions:
Object.create = function(prototype){
function F(){}
F.prototype = prototype;
return new F();
}
Copy the code
The idea is to define an empty constructor and then modify its prototype as a springboard to pass the prototype chain to the real Prototype.
Functional inheritance
The problem with both implementations is that there are no private properties or methods. In other words, there is a risk of tampering. So let’s solve this problem with functionalization.
function book(spec, my){
var that = {};
// Private variables
spec.name = spec.name || ' '; / / title
spec.page = spec.page || 0; / / number of pages
spec.classify = spec.classify || ' '; / / type
var getName = function(){
console.log(spec.name);
};
var getPage = function(){
console.log(spec.page);
};
var getClassify = function(){
console.log(spec.classify);
};
that.getName = getName;
that.getPage = getPage;
that.getClassify = getClassify;
return that;
}
function computer(spec, my){
spec = spec || {};
spec.classify = 'computer';
var that = book(spec, my);
var say = function(){
console.log('I\'m '+ spec.name);
};
that.say = say;
return that;
}
var Ninja = computer({name: 'JavaScript Ninja Secrets'.page: 350});
Copy the code
The advantage of functionalization is better encapsulation and information hiding. One may wonder why methods are declared and exposed in the following way:
var say = function(){
console.log('I\'m '+ spec.name);
};
that.say = say;
Copy the code
To protect the integrity of the object itself. Even if that. Say is tampered with or corrupted externally, the say method inside function Computer still works. Also, explain that, spec, and my:
that
It’s an open data storage container, where exposed data interfaces gospec
Is used to store the information needed to create a new instance, belongs to the data edited between instancesmy
It is used to store the private data container shared between the parent class and the child class, which is not accessible externally.
ES6 inheritance
Finally, take a look at class inheritance in the modern version of ES6. Can not help feeling before slash-and-burn farming, is how torture 🌚
class Book {
constructor() {this.name = ' '; / / title
this.page = 0; / / number of pages
this.classify = ' '; / / type
}
init(option) {
this.name = option.name || ' ';
this.page = option.page || 0;
this.classify = option.classify || ' ';
}
getName() {
console.log(this.name);
}
getPage (){
console.log(this.page);
}
getClassify (){
console.log(this.classify); }}class Computer extends Book{
constructor(... args){super(... args); } init(option) {super.init(option);
this.classify = 'computer';
}
say() {
console.log('I\'m '+ this.name); }}Copy the code
conclusion
While ES5 will eventually be phased out, it’s important to understand how it works. Because a lot of source code is still useful to the inside of the model. As a side value, ES5 inheritance is a piece of cake, while ES6 inheritance is a piece of cake.
Friends who like my articles can follow me in the following ways:
- “Star” or “watch” my GitHub blog
- RSS subscribe to my personal blog:Mr. Wang’s base