Although javascript is an object-oriented language, its inheritance mechanism was different from other traditional object-oriented languages since its inception. It is a prototype-based inheritance mechanism. However, under this mechanism, there are still some different implementation methods for inheritance.
Method 1: Classical inheritance
The so-called class inheritance refers to imitating the inheritance method of traditional object-oriented languages. Both the inheritance and the inherited parties are "classes". The code is as follows:
First define a parent class (or superclass):
function Person(name){ this.name=name; } Person.prototype.getName=function(){ return this.name; };The attributes of the parent class person are defined in the constructor, which can ensure that the name attribute of the subclass inherits it does not share this attribute with it, but belongs to the subclass separately. The getName method is mounted on the prototype in order to allow multiple instances of the subclass inheriting it to share this method body, so that memory can be saved (for multiple instances, every time an instance of New comes out, it will ensure that the getName method of these instances refers to the same memory space, rather than an independent space).
Define an inheritance method extend, 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; if(superClass.prototype.constructor==Object.prototype.constructor){ superClass.prototype.constructor=superClass; } }In this method, first create a new class F, let its prototype be the prototype of the parent class, and let the prototype of the subclass point to an instance of the class F, thus achieving the purpose of inheriting the parent class. At the same time, since the prototype of the subclass is modified, the constructor attribute of the modified prototype is pointed to the subclass, so that it has a constructor function, and at the same time, the subclass can mount a superClass attribute. The subclass can call the parent class through this property, thus establishing the relationship between the subclass and the parent class.
Define a subclass Author to inherit the parent class Person, as follows:
function Author(name,books){ Author.superClass.constructor.call(this,name); this.book=books; } extend(Author,Person); Author.prototype.getBooks=function(){ return this.book; }Here, the constructor of the parent class is called through its superClass attribute in the constructor of the subclass. At the same time, the call method is used to convert this pointer of the method call, so that the subclass Author also has (inherits) the properties of the parent class, and the subclass also has its own attribute book. Therefore, the parameter books are assigned to the attribute book in the constructor to achieve the purpose of construction. Use the extend function to inherit the properties and methods on the parent class Person prototype (actually, only the methods are inherited, because we just mounted the methods to the prototype before, and the properties are defined in the constructor). At the same time, Author has its own method getBooks, mounting it on the corresponding prototype, achieving the purpose of further expanding itself on the basis of inheritance.
This inheritance method is obviously a type inheritance similar to the traditional object-oriented language. The advantage is that it is easy for programmers who are accustomed to the traditional object-oriented concept. The disadvantage is that the process is relatively cumbersome and the memory consumption is slightly larger, because the subclass also has its own constructor and prototype, and the attributes of the subclass and the parent class are completely isolated. Even if the two are of the same value, they cannot share the same memory.
Method 2: Prototype inheritance
First, define a parent class. Here we will not deliberately imitate the use of constructors to define it, but directly define an object in the form of object literals, which is the parent class
var Person={ name:'default name', getName:function(){ return this.name; } } ;Like the first method, the object has a property name and a method getName.
Then define a cloning method to implement the inheritance of the subclass to the parent class, as follows:
function clone(obj){ function F(){} F.prototype=obj; return new F(); }The cloning method creates a new object, points the prototype of the object to the parent class, that is, the parameter obj, and returns the object at the same time.
Finally, the subclass inherits the parent class through the cloning function, as follows:
var Author=clone(Person); Author.book=['javascript']; Author.showBook=function(){ return this.book; }Here a subclass is defined, and the parent class Person is inherited through the clone function, and an attribute book is expanded, and a method showBook is expanded. Here, the subclass also has the attribute name, but it is the same as the name value of the parent class, so it is not overridden. If it is different, you can use it.
Author.name='new name'; Overwrite this property to get a new name attribute value of the subclass.
This prototype inheritance is simpler and more natural than class inheritance. At the same time, if the attributes of the subclass and the parent class attribute values are the same and can be modified, then they actually share the same memory space. For example, the name attribute above is difficult to understand for programmers who are accustomed to traditional object-oriented programs. If the two are to be chosen, this method is undoubtedly better.
Since JavaScript adopts a prototype-based approach to implement inheritance, and the prototype of each object can only point to an instance of a specific class (not to multiple instances), how to implement multiple inheritance (that is, let a class have methods and attributes of multiple classes at the same time, and does not define these methods and attributes themselves internally)?
In the JavaScript design pattern, a mixin class is given:
First, define a doping class to save some commonly used methods and attributes. These methods and attributes can be added to any other class through expansion, so that the added class has certain methods and attributes of the class. If multiple doping classes are defined and added to a class at the same time, then the class indirectly implements "multiple inheritance". Based on this idea, the implementation is as follows:
Definition of element-dominant class:
var Mixin=function(){}; Mixin.prototype={ serialize:function(){ var output=[]; for(key in this){ output.push(key+":"+this[key]); } return output.join(','); } }The doping class has a serialize method used to traverse itself, output its own attributes and attribute values, and return them as strings, separated by commas.
Define an expansion method to make a class have attributes or methods of a multi-group class after expansion, as follows:
function augment(receiveClass,givingClass){ if(arguments[2]){ for(var i= 2,len=arguments.length;i<len;i++){ receivingClass.prototype[arguments[i]]=givingClass.prototype[arguments[i]]; } } else { for(methodName in givingClass.prototype){ if(!receiveClass.prototype[methodName]){ receivingClass.prototype[methodName]=givingClass.prototype[methodName]; } } } }This method has two parameters by default. The first parameter accepts the expanded class, the second parameter is the doped class (used to expand other classes), and there can be other parameters. If it is greater than two parameters, the subsequent parameters are method or attribute names, which are used to indicate that the expanded class wants to inherit the specified attributes or methods of the doped class. Otherwise, all attributes and methods of the doped class are inherited by default. In this function, the first if branch is used to inherit the specified attributes and methods, and the else branch is the case where all attributes and methods are inherited by default. The essence of this method is to expand (add) the properties and methods on the prototype of the element doping class to the prototype of the expanded class, so that it has properties and methods of the element doping class.
Finally, use the expansion method to achieve multiple inheritance
augment(Author,Mixin); var author= new Author('js',['javascript design patterns']); alert(author.serialize());Here is a class of author. This class inherits from Person's parent class and also has methods and properties of the metabolized class Mixin. If you want, you can define N metabolized classes to expand the class. It can also inherit the properties and methods of other metabolized classes you define, so that multiple inheritance is realized. Finally, the operation result of the author's serialize method is as follows:
You will find that this class has both the properties and methods of the person class, Author class, and Mixin class. The properties and methods of Person and Mixin are all obtained through "inheritance". In fact, it realizes multiple inheritance.