1.原型链继承 缺点:在包含引用类型数据时,会被所有实例共享,容易造成修改的混乱,以及在创建子类型时不能向超类型传递参数 2.构造函数 通过在子类型的(构造)函数中调用超类型的构造函数来实现,解决了不能向超类型构造函数传递参数的缺点 缺点:无法实现函数的复用,并且超类型原型定义的方法子类型也没有办法访问到
function SuperType(){
this.color = ['red', 'blue', 'green']
}
function SubType(){
//继承了SuperType
SuperType.call(this);
}
let instance1 = new SubType();
instance1.color.push('purple');
3.组合继承 是将原型链和借用构造函数组合的一种方式,通过使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承 缺点:因为是以超类型的实例来作为子类型的原型,所以调用了两次超类的构造函数,造成了子类型的原型中多了很多不必要的属性
function SuperType(name){
this.name = name
this.color = ['red', 'blue', 'green']
}
SuperType.prototype.sayName = function(){
console.log(this.name);
}
function SubType(name, age){
//继承属性
SuperType.call(this, name);
this.age = age
}
//继承方法
SubType.prototype = new SuperType();
SubType.prototype.construct = SubType;
SubType.prototype.sayAge = function(){
console.log(this.age)
}
let instance1 = new SubType('names', 99)
instance1.color.push('black');
4.原型式继承 基于已有的对象来创建新的对象,实现原理是向函数中传入一个对象,然后返回一个以这个对象为原型的对象 该思路不是为了实现创造一种新类型,只是对某个对象实现一种简单继承,ES5中的 object.create()就是原型式继承 缺点和原型链方式相同 (一个传参, 一个属性共享)
function object(o){
function F(){};
F.prototype = o;
return new F();
}
5.寄生式继承 思路为创建一个用于封装继承过程的函数,通过传入一个对象,然后复制一个对象的副本,并对其进行扩展,最后返回该对象,扩展过程可理解是继承 优点是对一个简单对象实现继承,如果这个对象不是我们的自定义类型; 缺点是在为对象添加函数时,无法实现函数的复用
function createAnother(original){
let clone = object(original); //调用函数创建一个对象
clone.sayHi = function(){ //某种方式增强这个对象
console.log('Hello')
}
return clone;
}
let person = {name: 'names'};
let anotherPerson = createAnother(person);
anotherPerson.sayHi();
6.寄生式组合继承 组合继承的缺点就是使用超类型的实例作为子类型的原型,导致添加了不必要的原型属性,寄生式组合继承的方式是使用超类型的原型的副本 作为子类型的原型,这样就避免了创建不必要的属性
function inheritPrototype(subType, superType){
let prototype = object(superType.prototype); // 创建原型对象是超类原型对象的一个实例对象
prototype.constructor = subType; // 弥补因为重写原型而失去的默认的 constructor 属性
subType.prototype = prototype; // 实现原型继承
}