目录
一、原型链继承
让新实例的原型是另一个构造函数的实例
function Father(name: any) {
this.name = name;
}
Father.prototype.getName = function () {
console.log(this.name);
};
function Child(age: any) {
this.age = age;
}
Child.prototype = new Father('zhangsan');
const child = new Child('12');
console.log(child.name); // zhangsan
child.getName();
- 特点:新实例可继承的属性:实例的构造函数的属性、父类构造函数的属性、父类原型的属性
- 缺点:继承单一
二、借用构造函数继承
function Father(name: any) {
this.name = name;
}
Father.prototype.getName = function () {
console.log(this.name);
};
function Child(name: any) {
Father.call(this, name); //使用call 使得构造函数Father的this指向了Child
}
const child = new Child('lisi'); //lisi
console.log(child.getName()); //child.getName is not a function 没有继承父类原型上的方法
- 特点:只继承了父类构造函数的属性,没有继承父类构造函数的原型,可以给父类构造函数传参
- 缺点:只能继承父类构造函数的属性,每实例化一个薪实例,就会调用一次父类构造函数
三、组合继承(组合原型链继承和借用构造函数继承)
function Father(name: any) {
this.name = name;
}
Father.prototype.getName = function () {
console.log(this.name);
};
function Child(name: any) {
Father.call(this, name); //使用call 使得构造函数Father的this指向了Child
}
Child.prototype = new Father('lisi'); //lisi
const child = new Child('zhangsan');
console.log(child.name); //zhangsan
child.getName(); //zhangsan
- 特点: 结合1,2两种继承方法,原型链继承原型上的属性和方法,而通过构造函数继承实例属性,这样既可以把方法定义在原型上以实现重用,又可以让每个实例都有自己的属性
- 缺点:调用了两次父类构造函数,在子类借用构造函数继承时调用了一次,父类实例化的时候调用了一次
四、原型式继承
function child(obj: any) {
function F() {}
F.prototype = obj; //obj为父类的实例对象 相当于F的原型对象指向父类的实例对象
return new F(); //实例化了F 返回了F的实例对象
}
let obj = {
name: 'lhhh',
age: 18,
like: ['a', 'b'],
showName() {
console.log('my name is:', this.name);
},
};
const newChild = child(obj); //实例对象上不存在name 根据原型链往_proto_上找 找到了name
const newChild2 = child(obj); //实例对象上不存在name 根据原型链往_proto_上找 找到了name
newChild.name = 'httt';
newChild.like.push('c');
console.log(newChild); //like变为[a,b,c] name:'httt'
console.log(newChild2); //like变为[a,b,c] name:'lhhh'
- 特点:相当于复制一个对象, 用函数进行包装
- 缺点:引用类型的数据,一个子实例修改后,会导致所有的子实例的该数据都被修改。
五、寄生式继承
function child(obj: any) {
function F() {}
F.prototype = obj; //obj为父类的实例对象 相当于F的原型对象指向父类的实例对象
return new F(); //实例化了F 返回了F的实例对象
}
//寄生式继承
function changeData(obj: any) {
const newData = child(obj);
newData.age = 23;
return newData;
}
let obj = {
name: 'lhhh',
age: 18,
like: ['a', 'b'],
showName() {
console.log('my name is:', this.name);
},
};
const childInfo = changeData(obj); //经过这一步 函数变成了可以增删改的对象
console.log(childInfo);
- 特点:将最终结果改为了一个对象,对象可以进行增删改
六、寄生组合式继承
//创建父类
function Father(name: any) {
this.name = name;
}
//在父类原型上增加方法
Father.prototype.getName = function () {
console.log(this.name);
};
//创建子类
function Child(name: any) {
Father.call(this, name);
}
//新创建的对象保持指向Father的原型对象
Child.prototype = Object.create(Father.prototype);
const child = new Child('zhangsan');
child.getName(); //zhangsan
- 缺点:仍然调用了两次父类构造函数,这是组合式继承的通病