Prototype chain inheritance
Idea: let an instance object replace the prototype of the constructor, then the new instance object from the constructor has all the properties and methods of the current object and the methods on the prototype chain.
function Parent(age) { this.name = "father"; this.age = age; this.arr = [1, 2, 3, 4] } //Subclass function Child() { this.num = 12; } //The child class prototype points to the parent class instance Child.prototype = new Parent(50); let person= new Child(); console.log(person.age)//50
Disadvantages: Rewriting the prototype will result in the loss of the constructor attribute. If the parent class contains complex data types, the data types will be shared by the new subclasses.
let person2 = new Child(); person.arr.pop(); console.log(person2.arr); //[1,2,3]
Stealing constructor inheritance
Idea: in view of the problems existing in the prototype chain inheriting complex data types, use apply() or call() to point to the parent class in the subclass constructor, so that each time a new subclass is created, a new copy of the complex data types of the parent class will be re created, so that they will not affect each other.
function Parent(num) { this.age = 12; this.name = "Parent class"; this.num=num; this.foo = function () { console.log("father") } } function Child(num) { Parent.call(this,num); } let person=new Child(78); console.log(person.num)
Advantages: due to the action of apply and call, the subclass can pass parameters to the parent class, and the complex data types of this inheritance method will not affect each other.
Disadvantages: methods cannot be reused. foo in the Parent constructor of the above code is recreated every time a subclass creates a new object, which cannot be reused.
Supplement: new keyword function
1. Create an empty object
2. Point [[prototype]] of the new object to the prototype of the constructor
3 the constructor's this is assigned to the new object, that is, this points to the new object. This explains why stealing constructor inheritance can get the subclass this
4. Execute the code in the constructor to add attributes to the new object
5. Return new object
Combinatorial inheritance
Idea: in view of the advantages and disadvantages of prototype chain inheritance and stealing constructor, combinatorial inheritance is to inherit the inheritance method by prototype chain, so as to achieve reuse, and stealing constructor inherits other attributes.
function Parent(num) { this.age = 12; this.name = "Parent class"; this.num=num; } Parent.prototype.foo=function(){ console.log("father") } function Child(num) { Parent.call(this,num); } Child.prototype=new Parent();//An attribute is also added to the prototype let person=new Child(); person.foo()
Advantages: methods can be reused, and complex data types of parent classes will not affect each other
Disadvantages: performance problems. Although stealing the constructor to make the subclass attribute with the same name will mask the attribute with the same name on the prototype, the parent attribute actually adds two copies to the subclass, the first on the prototype and the second on the instance.
Prototype inheritance
Idea: similar to the factory function, I use the prototype chain inside a function to complete the inheritance operation and return a new object that inherits the parent class
Object contains a temporary constructor. Assign the incoming object to the prototype of this constructor, and then return an instance of this temporary type
function object(parentObj){ function F(){}; F.prototype=parentObj; return new F() } let parentObj = { name: "Nicholas", friends: ["Shelby", "Court", "Van"] }; let person=object(parentObj); console.log(parentObj.friends)
Disadvantages: in essence, like prototype chain inheritance, it is a shallow copy of objects, and complex data types are still problematic.
ES5 instantiates this method object Create () method, which accepts two parameters, the first is the inherited parent object, and the second parameter (optional) accepts that the object must be described in an attribute descriptor
let parentObj = { name: "Nicholas", friends: ["Shelby", "Court", "Van"] }; let person = Object.create(parentObj, { age: { value: 18, }, newName: { get() { return this.name } } })
Attribute descriptor supplement:
Data attribute: configurable (whether it can be deleted) enumerable (whether it can be traversed for in) writable (whether it can be rewritten) value: value
Accessor properties: configurable, enumerable, set, get
Parasitic inheritance
Idea: use an object () function to copy the parent class and return a new object, and then enhance the object
The object() function is not required for parasitic inheritance. Any function that returns a new object can be used here.
function create(parentObj) { let person = object(parentObj); // Get a new object person.say = function () { // Enhanced object console.log("name") } return person } //create new object function object(obj) { function F() {}; F.prototype = obj; return new F(); } let person = create({ name: "Zhang San" }) person.say()//Zhang San
Disadvantages: parasitic inheritance, like stealing constructors, will make it difficult to reuse enhanced object methods.
Parasitic combinatorial inheritance
Idea: use constructor to inherit attributes and parasitic inheritance prototype chain method.
function create(child, parent) { let protype = object(parent.prototype); protype.constructor = child; child.prototype = protype; } //create new object function object(obj) { function F() {}; F.prototype = obj; return new F(); } function Child() { Parent.call(this) } function Parent() { this.name = "father"; this.age = "12"; } Parent.prototype.sayName = function () { console.log("Zhang San") } //Parasitic inheritance method create(Child, Parent); let person = new Child();