First, prototype chain inheritance
Use an instance of a parent class as a prototype for a subclass
function Parent() {
this.isShow = true
this.info = {
name: "yhd".age: 18}; } Parent.prototype.getInfo =function() {
console.log(this.info);
console.log(this.isShow); // true
}
function Child() {};
Child.prototype = new Parent();
let Child1 = new Child();
Child1.info.gender = "Male";
Child1.getInfo(); // {name: "yhd", age: 18, gender: "male "}
let child2 = new Child();
child2.getInfo(); // {name: "yhd", age: 18, gender: "male "}
child2.isShow = false
console.log(child2.isShow); // false
Copy the code
Advantages:
1. Superclass methods can be reused
Disadvantages:
- All reference attributes (info) of the parent class are shared by all subclasses. Changing a reference attribute of one subclass affects the other subclasses as well
- Subtype instances cannot pass arguments to parent type constructors
Constructor inheritance
The call() and apply() methods can be used in the subclass constructor to call the superclass constructor
function Parent() {
this.info = {
name: "yhd".age: 19,}}function Child() {
Parent.call(this)}let child1 = new Child();
child1.info.gender = "Male";
console.log(child1.info); // {name: "yhd", age: 19, gender: "male "};
let child2 = new Child();
console.log(child2.info); // {name: "yhd", age: 19}
Copy the code
By using the call() or apply() methods, the Parent constructor is executed in the context of a new object created for the Child instance, which is equivalent to running all the initialization code in the Parent() function on the new Child instance object, resulting in each instance having its own info attribute.
1. Pass parameters
One advantage of a stolen constructor over stereotype chain inheritance is that arguments can be passed in the subclass constructor as in the superclass constructor.
function Parent(name) {
this.info = { name: name };
}
function Child(name) {
// inherits from Parent and passes the parameter
Parent.call(this, name);
// Instance properties
this.age = 18
}
let child1 = new Child("yhd");
console.log(child1.info.name); // "yhd"
console.log(child1.age); / / 18
let child2 = new Child("wxb");
console.log(child2.info.name); // "wxb"
console.log(child2.age); / / 18
Copy the code
In the example above, the Parent constructor takes a name argument and assigns it to an attribute. Passing this argument when the Parent constructor is called in the Child constructor actually defines the name attribute on the Child instance. To ensure that the Parent constructor does not override attributes defined by the Child, you can add additional attributes to the subclass instance after calling the Parent constructor
Advantages:
- Arguments can be passed to the parent class in the subclass constructor
- Reference properties of the parent class are not shared
Disadvantages:
- Subclasses do not have access to methods defined on Parent class prototypes (that is, methods defined on Parent. Prototype), so all method properties are written in constructors that are initialized each time an instance is created
3. Combinatorial inheritance
Composite inheritance combines the advantages of stereotype chain inheritance and embeded constructor inheritance (constructor inheritance),
The basic idea is to use a stereotype chain to inherit properties and methods from the stereotype and a constructor to inherit instance properties, so that methods can be defined on the stereotype for reuse and each instance can have its own properties
function Parent(name) {
this.name = name
this.colors = ["red"."blue"."yellow"]
}
Parent.prototype.sayName = function () {
console.log(this.name);
}
function Child(name, age) {
// Inherits the superclass attributes
Parent.call(this, name)
this.age = age;
}
// Inherits the parent method
Child.prototype = new Parent();
Child.prototype.sayAge = function () {
console.log(this.age);
}
let child1 = new Child("yhd".19);
child1.colors.push("pink");
console.log(child1.colors); // ["red", "blue", "yellow", "pink"]
child1.sayAge(); / / 19
child1.sayName(); // "yhd"
let child2 = new Child("wxb".30);
console.log(child2.colors); // ["red", "blue", "yellow"]
child2.sayAge(); / / 30
child2.sayName(); // "wxb"
Copy the code
In the example above, the Parent constructor defines the name and colors attributes, and then adds a sayName() method to its prototype. The Parent constructor is called inside the Child constructor, passing in the name argument, and child.prototype is assigned to the Parent instance, then adding a sayAge() method to its prototype. This creates two instances of child1 and child2, each with its own attributes, including colors, and sharing the sayName method of the parent class
Advantages:
- Methods of the parent class can be reused
- You can pass parameters to the Parent constructor from the Child constructor
- Referenced properties in the parent constructor are not shared
Iv. Inheritance of the original type
A shallow copy of a parameter object
function objectCopy(obj) {
function Fun() {}; Fun.prototype = obj;return new Fun()
}
let person = {
name: "yhd".age: 18.friends: ["jack"."tom"."rose"].sayName:function() {
console.log(this.name); }}let person1 = objectCopy(person);
person1.name = "wxb";
person1.friends.push("lily");
person1.sayName(); // wxb
let person2 = objectCopy(person);
person2.name = "gsr";
person2.friends.push("kobe");
person2.sayName(); // "gsr"
console.log(person.friends); // ["jack", "tom", "rose", "lily", "kobe"]
Copy the code
Advantages:
- Superclass methods are reusable
Disadvantages:
- References to the parent class are shared by all subclasses
- A subclass instance cannot pass arguments to its parent class
The object.create () method of ES5 has the same effect as the objectCopy() method here with only the first argument
Parasitic inheritance
Make a shallow copy of a target object using primitive inheritance to enhance the capability of the shallow copy
function objectCopy(obj) {
function Fun() {}; Fun.prototype = obj;return new Fun();
}
function createAnother(original) {
let clone = objectCopy(original);
clone.getName = function () {
console.log(this.name);
};
return clone;
}
let person = {
name: "yhd".friends: ["rose"."tom"."jack"]}let person1 = createAnother(person);
person1.friends.push("lily");
console.log(person1.friends);
person1.getName(); // yhd
let person2 = createAnother(person);
console.log(person2.friends); // ["rose", "tom", "jack", "lily"]
Copy the code
Parasitic combination inheritance
function objectCopy(obj) { function Fun() { }; Fun.prototype = obj; return new Fun(); } function inheritPrototype(child, parent) { let prototype = objectCopy(parent.prototype); Prototype. Constructor = child; // Add object Child. Prototype = prototype; } function Parent(name) {this.name = name; this.friends = ["rose", "lily", "tom"] } Parent.prototype.sayName = function () { console.log(this.name); } function Child(name, age) { Parent.call(this, name); this.age = age; } inheritPrototype(Child, Parent); Child.prototype.sayAge = function () { console.log(this.age); } let child1 = new Child("yhd", 23); child1.sayAge(); // 23 child1.sayName(); // yhd child1.friends.push("jack"); console.log(child1.friends); // ["rose", "lily", "tom", "jack"] let child2 = new Child("yl", 22) child2.sayAge(); // 22 child2.sayName(); // yl console.log(child2.friends); // ["rose", "lily", "tom"]Copy the code
Advantages:
- The superclass constructor is called only once
- Child can pass parameters to Parent
- Superclass methods can be reused
- Reference properties of the parent class are not shared
Parasitic combinatorial inheritance is the best model for reference type inheritance