| 「这是我参与11月更文挑战的第13天,活动详情查看:2021最后一次更文挑战」 |
|---|
继承有6种常用的实现方式
- 原型链继承:
让新实例的原型等于父类的实例。 - 借用构造函数(类式继承):
用.call()和.apply()将父类构造函数引入子类函数(在子类函数中做了父类函数的自执行(复制)) - 组合式继承(组合原型链继承和借用构造函数继承)(常用)
结合了两种模式的优点,传参和复用 - 原型式继承
- 寄生式继承
- 寄生组合式继承(常用)
想要继承,就必须要提供个父类(继承谁,提供继承的属性)
// 父类---------------------------
function Person(name){ //给构造函数添加参数
this.name=name
this.sayName =function(){
alert(this.name)
}
}
Person.prototype.age = 18; //给构造函数添加了原型属性
1. 原型链继承:让新实例的原型等于父类的实例。
特点- 实例可继承的属性有:实例的构造函数的属性,父类构造函数属性,父类原型的属性。(新实例不会继承父类实例的属性!)
缺点-
新实例无法向父类构造函数传参。
-
继承单一。
-
所有新实例都会共享父类实例的属性。(原型上的属性是共享的,一个实例修改了原型属性,另一个实例的原型属性也会被修改!)
-
// 原型链继承---------------------------
function Per(){
this.name = 'panpan';
}
Per.prototype= new Person(); //重点
var per1 = new Per();
console.log(per1.age); // 18
// instanceof判断元素是否在另一个元素的原型链上
console.log(per1 instanceof Person); //true
2. 借用构造函数(类式继承):用.call()和.apply()将父类构造函数引入子类函数(在子类函数中做了父类函数的自执行(复制))
- 特点:
1. 只继承了父类构造函数的属性,没有继承父类原型的属性。
2. 解决了原型链继承缺点1、2、3。
3. 可以继承多个构造函数属性(call多个)。
4. 在子实例中可向父实例传参。
- 缺点:
1. 只能继承父类构造函数的属性。
2. 无法实现构造函数的复用。(每次用每次都要重新调用)
3. 每个新实例都有父类构造函数的副本,臃肿。
// 借用构造函数继承---------------------
function Con(){
Person.call(this,'ava'); //重点
this.age = 21
}
var con1 = new Con()
console.log(con1.name) //ava
console.log(con1.age) //21
console.log(con1 instanceof Person) //false
3. 组合式继承(组合原型链继承和借用构造函数继承)(常用) 结合了两种模式的优点,传参和复用
特点:- 可以继承父类原型上的属性,可以传参,可复用。
- 每个新实例引入的构造函数属性是私有的。
缺点:调用了两次父类构造函数(耗内存),子类的构造函数会代替原型上的那个父类构造函数。
// 组合原型链继承和借用构造函数继承
function SubType(name){
Person.call(this,name); //借用构造函数模式
}
SubType.prototype= new Person(); //原型链继承
var sub = new SubType('lian')
console.log(sub.name) //lian 继承构造函数属性
console.log(sub.age) //18 继承父类原型属性