One of the most important aspects of object-oriented programming is the inheritance of objects. By inheriting from object B, object A directly owns all the properties and methods of object B。This is very useful for reuse.
Most object-oriented programming languages use classes to implement object inheritance. Traditionally, inheritance in the j**ascript language has not been implemented through classes (ES6 introduced the class syntax), but through "prototypes". So how many common inheritance methods are there in JS?
The key to this approach is:The prototype of a child type is an instance object of the parent type.
Parent type function person(name, age) personprototype.setage = function () subtype function student(price) studentThe prototype of the prototype = new person() subtype is an instance object of the parent type, var s1 = new student(15000), var s2 = new student(14000) consolelog(s1,s2)
But the essence of this approach is to point the prototype of the child class to an instance of the parent class, soInstances of subclasses can then be accessed to studentprototype is also an instance of person, so that you can access the private methods of the parent class, and then point to the prototype of the parent class by proto to get the methods on the prototype of the parent class。As a result, the private and public methods and properties of the parent class are treated as the public properties of the child class.
A child class inherits the properties and methods of the parent class, and treats the private properties and public methods of the parent class as its own public properties and methodsIf there is a reference type property in the private property of the parent class, then it will be used as a public property when it is inherited by the subclass, so that when subclass 1 operates this property, it will affect subclass 2.
s1.play.push(4)console.log(s1.play, s2.play)console.log(s1.__proto__ === s2.__proto__)=== s2.__proto__.proto__)//true
The play attribute changes in S1, and the play attribute changes in S2 as well.
Another thing to note is,When we need to add a new method to a child class or override a method from a parent class, be sure to put it after the statement that replaces the prototype
function person (name, age) person.prototype.setage = function ()function student (price) }// student.prototype.sayhello = function() Writing the prototype method and properties of the subclass here is invalid, because it will change the direction of the prototype, so it should be put after the redesignationprototype = new person()student.prototype.sayhello = function ()var s1 = new student(15000)console.log(s1)
Features:
The new prototype method prototype property for the parent class is simple and easy to implement for all subclassesCons:
It is not possible to achieve multiple inheritances of all properties from the prototype object that are shared by all instancesWhen creating a subclass instance, it is not possible to pass parameters to the parent class constructor In order to add properties and methods to the subclass, it is necessary to use thestudent.prototype = new person()
After that, the key to not putting it in the constructor is as follows:In the subtype constructor, the generic call() calls the parent type constructor
function person(name, age) person.prototype.setage = function ()function student(name, age, price) var s1 = new student('tom', 20, 15000)
This approach only implements partial inheritance, and if the parent class prototype also has methods and properties, the child class will not be able to get them.
console.log(s1.setage())//uncaught typeerror: s1.setage is not a function
Features:
Solved the problem that child class instances share parent class reference properties in prototype chain inheritance, and when creating a child class instance, parameters can be passed to the parent class, and multiple inheritance (call multiple parent class objects) can be implementedCons:
The instance is not an instance of the parent class, but the instance of the child class can only inherit the instance properties and methods of the parent class, and cannot inherit the properties and methods of the prototype to achieve function reuseBy calling the parent class construct, inheriting the properties of the parent class and retaining the advantages of passing parameters, and then by using the parent class instance as a child class prototype, the function is reused.
function person (name, age) }person.prototype.setage = function ()function student (name, age, price) }student.prototype = new person()student.prototype.constructor = student combinatorial inheritance is also the student. that the constructor points to needs to be fixedprototype.sayhello = function ()var s1 = new student('tom', 20, 15000)var s2 = new student('jack', 22, 14000)console.log(s1)console.log(s1.constructor) //person
This approach combines the advantages of prototype chain inheritance and constructors, and is the most commonly used inheritance mode in j**ascript. The downside is that the constructor is called twice in any case: once when creating a prototype of a subtype, and once inside the subtype constructor, which eventually contains all the instance properties of the parent object, but we have to override those properties when calling the subclass constructor.
Pros:
You can inherit the instance property method, or you can inherit the prototype property method, there is no reference property sharing problem, and the parameter function can be reusedCons:
The parent constructor was called twice, resulting in two instancesIn this way, the parent class archetype and the child class archetype point to the same object, and the child class can inherit to the parent class's public method as its own public method, and does not initialize the twice-instance method property, avoiding the disadvantages of combinatorial inheritance
function person (name, age) }person.prototype.setage = function ()function student (name, age, price) }student.prototype = person.prototypestudent.prototype.sayhello = function ()var s1 = new student('tom', 20, 15000)console.log(s1)
However, there is no way to tell whether the object is a child or a parent instantiation.
console.log(s1 instanceof student, s1 instanceof person)//true trueconsole.log(s1.constructor)//person
Pros:
The twice-instance method property is not initialized, avoiding the drawbacks of combinatorial inheritanceCons:
There is no way to tell if the instance was created by a child or a parent, and the constructor of the child and parent class points to the same. Prototypes allow you to create objects based on what you already havevar b = object.create(a)
Based on object A, object B is generated. b inherits all of a's properties and methods.
function person (name, age) person.prototype.setage = function ()function student (name, age, price) }student.prototype = object.create(person.prototype) core **studentprototype.constructor = student core**var s1 = new student('tom', 20, 15000)console.log(s1 instanceof student, s1 instanceof person) // true trueconsole.log(s1.constructor)
Similarly, student inherits all of the properties and methods of the Person prototype object. By far, the perfect inheritance method!
ES6 introduces the class keyword, which can be inherited by the extends keyword, and can also define the static method of the class through the static keyword, which is much clearer and more convenient than ES5 which implements inheritance by modifying the prototype chain.
Inheritance in ES5 essentially creates an instance object of the child class this, and then adds the parent class's methods on top of this (parent.).apply(this))。ES6 has a completely different inheritance mechanism, essentially adding the properties and methods of the parent class instance object to this (so you have to call the super method first), and then modify this with the constructor of the child class.
It should be noted that the class keyword is just syntactic sugar for the prototype, and j**ascript inheritance is still based on the prototype
class person defines the general method showname()let p1 = new person('kobe', 39)console.log(p1) defines a subclass: class student extends person showname () let s1 = new student('wade', 38, 1000000000)console.log(s1)s1.showname()
Pros:
The grammar is simple and easy to understand, and the operation is more convenientCons:
Not all browsers support the class keywordjs several ways to implement inheritancej**ascript multiple ways and advantages and disadvantages of in-depth inheritancej**ascript common inheritance methodsRuan Yifeng es6 introductory class inheritance method 5: Combinatorial inheritance optimization 2 I think it can also be written like this:
function person (name, age) person.prototype.sayname = function() function student (name, age, price) student.prototype = object.create(person.prototype);student.prototype.constructor = student;Here the sayage prototype method is placed after the inheritance statement to prevent s1sayage() error, for details, refer to Method 2: Borrow the constructor to inherit studentprototype.sayage = function() var p1 = new person('join', 30);var s1 = new student('tom', 20, 1500);console.log(p1.sayname())// joinconsole.log(s1.sayage())// 20