The concrete implementation method of js class inheritance

  • 2020-03-30 01:11:32
  • OfStack

The following three methods of js implementation inheritance are provided: class inheritance, prototype inheritance and admixture metaclass. Here is a brief description of class inheritance, the latter two in the back of the simple in brief, please pay more attention to, guidance, thank you.

Class inheritance.

The implementation of js class inheritance relies on the prototype chain. What is a prototype chain? Objects in js have a property called prototy, which returns a reference to the object type that provides a set of basic functionality for the object's class.

I think I've got a good memory for prototype, and by the way, we use code like this a lot.


var Person = function(){    
    this.name = "liyatang";
};
Person.prototype = {
    //The basic functionality of Person can be provided here
    getName : function(){
        return this.name;
    }
}

We put the basic functionality of the class in the prototype property to indicate that the reference to the object Person has XXX functionality.

After you understand the prototype, you need to understand what the prototype chain is. When accessing a member of an object (property or method), if the member is not present in the current object, js will look for it in the object referred to by the prototype property. If it is not found, js will continue to look in the object referred to by the prototype at the next level until it is found. Will return undifined if not found.

So what does the prototype chain give us? It is easy to imagine that the prototype chain means that one class inherits another class by simply setting the prototype of a subclass to point to an instance of the parent class. This binds the member of the parent class to the child class, because when a member is not found on the child class, it is found in the parent class. (the above two words are not rigorous, only in plain language description)

Next, we need a Chinese class, and we need to inherit the name and getName members of the Person class.


var Chinese = function(name, nation){
        //Inheritance, need to call the constructor of the parent class, can be called with call, this points to Chinese
    //Place Person on this scope to invoke a member of Person
    Person.call(this,name);
    this.nation = nation;
};
Chinese.prototype = Person.prototype;
//This is not the same as before because the prototype property is overridden
//Chinese.prototype = {
//  getNation : function(){
//      return this.nation;
//  }
//};
//I'm going to do it this way for the rest of the way
Chinese.prototype.getNation = function(){
        return this.nation;
};

The inheritance relationship is established, and we call it this way


var c = new Chinese("liyatang","China");
alert(c.getName());// liyatang

So class inheritance is done. If you're really done, set a breakpoint in alert with firebug, and you'll notice that the original person.prototype has been modified to add the getNation method.
< img border = 0 SRC = "/ / files.jb51.net/file_images/article/201312/20131231145241630.jpg" >

This is because the code above is chinese.prototype = person.prototype; This is the reference type. Modifying Chinese also modifies Person. This in itself is intolerable and creates strong coupling between classes, which is not the effect we want.

We can weaken the coupling by creating another object or instantiating an instance.


//The first kind of
//Chinese.prototype = new Person();
//The second,
//var F = function(){};
//F.prototype = Person.prototype;
//Chinese.prototype = F.prototype;

What's the difference between the two methods? In the second case, an empty function F is added to avoid creating an instance of the parent class, since the parent class is likely to be large and the constructor of the parent class will have some side effects or perform a lot of computation. So I strongly recommend the second method.

That's it. It's over. Not yet! Under an object's property prototype there is a property constructor, which holds a reference to a function that constructs a particular object instance. According to the Chiese. Prototype. The constructor should be equal to the Chinese, in fact is not.

Recall that when we set Chiese's prototype chain, we overwrote chiese.prototype with person.prototype. So at this time of Chiese. Prototype. The constructor is the Person. We also need to add the following code


//Here does not need to scrutinize the if condition, know Chinese. The prototype. The constructor = Chinese will do
if(Chinese.prototype.constructor == Object.prototype.constructor){
    Chinese.prototype.constructor = Chinese;
}

Clean up the code as follows


var Person = function(name){
    this.name = name;
};
Person.prototype = {
    getName : function(){
        return this.name;
    }
};

var Chinese = function(name, nation){
    Person.call(this,name);
    this.nation = nation;
};
var F = function(){};
F.prototype = Person.prototype;
Chinese.prototype = F.prototype;
if(Chinese.prototype.constructor == Object.prototype.constructor){
    Chinese.prototype.constructor = Chinese;
}
Chinese.prototype.getNation = function(){
        return this.nation;
};

var c = new Chinese("liyatang","China");
alert(c.getName());

If you can put the inherited code in a function, convenient code reuse, the final arrangement of the code as follows


function extend(subClass,superClass){
    var F = function(){};
    F.prototype = superClass.prototype;
    subClass.prototype = new F();
    subClass.prototype.constructor = subClass;
    subClass.superclass = superClass.prototype; //Added an attribute to the parent class itself to call the parent function
    if(superClass.prototype.constructor == Object.prototype.constructor){
        superClass.prototype.constructor = superClass;
    }
}

var Person = function(name){
    this.name = name;
};
Person.prototype = {
    getName : function(){
        return this.name;
    }
};

var Chinese = function(name, nation){
    Person.call(this,name);
    this.nation = nation;
};
extend(Chinese, Person);
Chinese.prototype.getNation = function(){
        return this.nation;
};

var c = new Chinese("liyatang","China");
alert(c.getName());

Revised after publication:

In the comments on the first floor, I have a new take on the extend function. Two approaches were suggested earlier in the discussion on how to set up a prototype chain

The same code at the page code block index 3

Although the second method reduces the method of calling the constructor of the parent class, it USES person.call (this,name) when designing the Chinese class. This is also equivalent to calling the constructor of the parent class.

However, by using the first method, we can reduce the need to write person. call(this,name) in Chinese; This part of the code is often forgotten in subclasses. You might as well put this kind of functionality in extend. Just write

Chinese. The prototype = new Person (); The same is true: the coupling is weak.

What I forgot is that chinese.prototype = new Person(); That's the right way to write it. The answer is no! Obviously new Person() needs to pass a name parameter. We couldn't do this in the extend function, so we had to call the constructor of the parent class in the Chinese class. This is also in line with the object-oriented approach.

Therefore, the second method is still recommended.

This is the first time to write an article about technology, basically according to their own ideas spread out, it is inevitable that there will be some places not considered and explanation is not clear, please leave a message feedback, thank you.


Related articles: