1. Simple prototype chain
// 创建要继承的父类
function Father() {
// 自带的属性和方法
this.name = "li";
this.show = function() {
console.log("帅");
}
};
// 在父类的原型上添加方法
Father.prototype.callback = function() {
console.log(this.name);
}
// 定义Son
function Son() {
}
// 令Son继承Father
Son.prototype = new Father();// 这句是原型链继承的重点
// 创建Son的对象实例
var son = new Son();
var son1 = new Son();
console.log(son.name); // 可以调用继承于父类上的属性
son.show(); // 可以调用继承于父类上的方法
son1.callback(); // 可以调用father中原型上添加的方法
Focus :
Let the prototype of the new instance equal the instance of the parent class.
Advantages :
Simple and easy to implement
Disadvantages :
- The reference properties of the prototype object are shared by all instances .
// 创建要继承的父类
function Father() {
// 自带的属性和方法
this.name = "li";
};
// 定义Son
function Son() {
}
// 令Son继承Father
Son.prototype = new Father(); // 这句是原型链继承的重点
// 创建Son的对象实例
var son = new Son();
var son1 = new Son();
son1.__proto__.name = "zhang"; //通过一个实例改变Son的prototype上的name
// 导致所有实例的name都改变,就叫做引用值共享
console.log(son.name); //"zhang"
console.log(son1.name); //"zhang"
- When creating a subclass instance, you cannot pass parameters to the parent class constructor
- Single inheritance
2. Constructor inheritance
// 创建父类
function Father(name) {
this.name = name;
this.arr = [1];
this.show = function() {
console.log("shuai");
}
}
Father.prototype.call = function() {
console.log("call");
};
// 创建子类
function Son(name) {
// 借父类的构造函数来增强子类实例,等于是把父类的实例属性复制了一份给子类实例装上了(完全没有用到原型)
Father.call(this, name); // 核心代码
}
var son1 = new Son("n1");
var son2 = new Son("n2");
son1.arr.push(2); // 向son1的数组中添加一个数
console.log(son1);
console.log(son2);
// 这时son实例的prototype的原型是object
console.log(son1.show === son2.show); // false
Focus :
Use .call() and .apply() to introduce the parent class constructor into the subclass function (self-execution (copy) of the parent class function is done in the subclass function)
Advantages :
- Only inherit the properties of the parent class constructor, not the properties of the parent class prototype
- Solve the shortcomings of prototype chain inheritance
- Can inherit the attributes of multiple constructors (using call())
- In the child instance, parameters can be passed to the parent instance.
Disadvantages :
- Can only inherit the properties of the parent class constructor
- Unable to realize the reuse of the constructor (recall each time it is used)
- Each new instance has a copy of the parent class constructor, bloated
3. Combination inheritance (combined prototype chain inheritance and borrowed constructor inheritance) (commonly used)
// 创建父类
function Father(name) {
this.name = name;
this.arr = [1];
this.show = function() {
console.log("shuai");
}
}
Father.prototype.call = function() {
console.log("call");
};
function Son(name) {
Father.call(this, name); // 借用构造函数继承
};
Son.prototype = new Father(); // 原型链继承
var son1 = new Son('li');
var son2 = new Son('zhang');
console.log(son1);
console.log(son2);
Focus :
Combines the advantages of the two modes, parameter transfer and multiplexing
Advantages :
- Can inherit the attributes on the parent class, can pass parameters, can be reused
- The constructor attributes introduced by each new instance are private .
Disadvantages :
The parent class constructor is called twice (memory consumption), and the subclass constructor will replace the parent class constructor on the prototype.
4. Prototype inheritance
// 创建父类
function Father(name) {
this.name = name;
this.arr = [1];
this.show = function() {
console.log("shuai");
}
}
Father.prototype.call = function() {
console.log("call");
};
// 生育函数
function beget(obj) {
function F() {
}
F.prototype = obj; //继承了传入的参数
return new F(); //返回函数对象
}
var son1 = new Father(); // 先拿到父类的对象
console.log(son1);
// (核心代码)
var son2 = beget(son1); // 将父类中的属性赋值到每一个子类的函数的原型中
var son3 = beget(son1); // 同上
son2.name = "zhang"; // 修改实例中的属性
console.log(son2);
console.log(son3);
console.log(son2.call); //子类的实例都可以访问父类的原型上的属性和方法
Focus :
Wrap an object with a function, and then return the call of this function. This function becomes an instance or object that can add properties at will. (Each time an object instance is created, a new function is returned),
Advantages :
Copy an object and wrap it with a function.
Disadvantages :
- All instances inherit the properties on the prototype.
- Unable to achieve reuse.
V. Parasitic inheritance
// 创建父类
function Father(name) {
this.name = name;
this.arr = [1];
this.show = function() {
console.log("shuai");
}
}
Father.prototype.call = function() {
console.log("call");
};
function beget(obj) {
function F() {
}
F.prototype = obj; //继承了传入的参数
return new F(); //返回函数对象
}
var son = new Father();
// 将原型式继承的核心代码套一个壳子
function getSubObject(obj) {
var clone = beget(obj); // 核心
return clone;
}
var son1 = getSubObject(new Father());
console.log(son1);
Focus :
It puts a shell around prototype inheritance.
Advantages :
No custom type is created, because it just sets a shell to return the object (this one), this function naturally becomes a new object created.
Disadvantages :
The prototype is not used and cannot be reused.
6. Parasitic combined inheritance (commonly used)
Parasite :
Return the object in the function and then call
Combination :
1. The prototype of the function is equal to another instance.
2. Use apply or call to introduce another constructor in the function, which can pass parameters
// 创建父类
function Father(name) {
this.name = name;
this.arr = [1];
this.show = function() {
console.log("shuai");
}
}
Father.prototype.call = function() {
console.log("call");
};
function beget(obj) {
function F() {
}
F.prototype = obj; //继承了传入的参数
return new F(); //返回函数对象
}
var bet = beget(Father.prototype);
// 继承了父类函数的原型
function Son() {
Father.call(this);
}
Son.prototype = bet; //继承了get的实例;
bet.constructor = Son; // 修复实例
var son1 = new Son();
// Sub的实例就继承了构造函数的属性,父类实例,
console.log(son1.call);
Key point : fixed the problem of combinatorial inheritance