JS中实现继承的几种方式及优缺点
1、原型链继承
主要利用sub.prototype=new super,即让子类的显示原型成为父类的一个实例对象,这样子类的实例对象就可以通过隐式原型链找到父类的属性和方法了。
//父类
function Super(){
this.flag = true;
}
Super.prototype.getFlag = function(){
return this.flag;
}
function Sub(){
this.subFlag = false;
}
//实现继承
Sub.prototype = new Super;
//给子类添加子类特有的方法,注意顺序要在继承之后
//构造实例
var obj = new Sub; 优点: 1.非常纯粹的继承关系,实例是子类的实例,也是父类的实例
2.父类新增原型方法/原型属性,子类都能访问到
3.简单,易于实现
2.父类新增原型方法/原型属性,子类都能访问到
3.简单,易于实现
缺点:
1.包含引用类型值的原型属性会被所有实例共享,这会导致对一个实例的修改会影响另一个实例。
2.在创建子类型的实例时,不能向超类型的构造函数中传递参数。由于这两个问题的存在,实践中很少单独使用原型链。
2.在创建子类型的实例时,不能向超类型的构造函数中传递参数。由于这两个问题的存在,实践中很少单独使用原型链。
2、构造函数继承
在子类中使用call、apply或者bind改变this指向,使用父类的构造函数。
function Super(){
this.flag = true;
}
function Sub(){
Super.call(this) //如果父类可以需要接收参数,这里也可以直接传递
}
var obj = new Sub();
obj.flag = flase;
var obj_2 = new Sub();
console.log(obj.flag) //依然是true,不会相互影响 优点: 1.解决了1中,子类实例共享父类引用属性的问题
2.创建子类实例时,可以向父类传递参数
3.可以实现多继承(call多个父类对象)
2.创建子类实例时,可以向父类传递参数
3.可以实现多继承(call多个父类对象)
缺点:
1.实例并不是父类的实例,只是子类的实例
2.只能继承父类的实例属性和方法,不能继承父类原型属性/方法
3.无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
2.只能继承父类的实例属性和方法,不能继承父类原型属性/方法
3.无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
3、组合继承(伪经典继承)
将原型链和借用构造函数的技术组合在一起。原理是:使用原型链实现对原型属性和方法的继承,而通过借用构造函数实现对实例属性的继承。
function Super(){
this.flag = true;
} Super.prototype.getFlag = function(){
return this.flag; //继承方法
}
function Sub(){
this.subFlag = flase
Super.call(this) //继承属性
}
Sub.prototype = new Super;
var obj = new Sub();
Sub.prototype.constructor = Sub;
Super.prototype.getSubFlag = function(){
return this.flag;
}
缺点:调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了)
4、寄生组合继承(经典继承)
将上面3的 Sub.prototype = new Super 使用Object.create方法实现。即Sub.prototype=Object.create(Super.prototype)。
优点:
避免了组合继承中构造函数调用了两次的弊端。


查看20道真题和解析