es5继承方式
我了解的 js 中实现继承的几种方式有:
1.原型链的方式来实现继承
但是这种实现方式存在的缺点是,在包含有引用类型的数据时,会被所有的实例对象所共享,容易造成修改的混乱。还有就是在创建子类型的时候不能向超类型传递参数。
缺点:
- 包含引用类型的原型属性会被所有实例属性共享,容易造成属性的修改混乱。
- 在创建子类型的实例时,不能向超类型的构造函数中传递参数。
function Parent(name){
this.name = name;
}
Parent.prototype.say = function(){
console.log('====name====',this.name);
}
function Child(){}
Child.prototype = new Parent('child');
2.使用借用构造函数的方式
这种方式是通过在子类型的函数中调用超类型的构造函数来实现的,这一种方法解决了不能向超类型传递参数的缺点,但是它存在的一个问题就是无法实现函数方法的复用,并且超类型原型定义的方法子类型也没有办法访问到。
优点
解决了原型链实现继承的不能传参的问题和父类的原型共享的问题。
缺点
和构造函数模式一样的问题,所有的方法都在构造函数中定义,因此就无法做到函数的复用。而且超类型的原型中定义的方法,对于子类型而言也是不可见的。
function Child(...args){
Parent.apply(this,args);
}
3.组合继承
组合继承是将原型链和借用构造函数组合起来使用的一种方式。通过借用构造函数的方式来实现类型的属性的继承,通过将子类型的原型设置为超类型的实例来实现方法的继承。这种方式解决了上面的两种模式单独使用时的问题,但是由于我们是以超类型的实例来作为子类型的原型,所以调用了两次超类的构造函数,造成了子类型的原型中多了很多不必要的属性。
优点
组合继承避免了原型链和借用构造函数的缺陷,融合了它们的优点,成为 JavaScript 中最常用的继承模式。而且,instanceof 和 isPropertyOf() 也能够用于识别基于组合继承创建的对象。
缺点
调用了两次超类的构造函数,导致基类的原型对象中增添了不必要的超类的实例对象中的所有属性。
function Child(...args){
Parent.apply(this,args);
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;
4.原型式继承
原型式继承的主要思路就是基于已有的对象来创建新的对象,实现的原理是,向函数中传入一个对象,然后返回一个以这个对象为原型的对象。这种继承的思路主要不是为了实现创造一种新的类型,只是对某个对象实现一种简单继承,ES5 中定义的 Object.create() 方法就是原型式继承的实现。缺点与原型链方式相同。
优点
可以实现基于一个对象的简单继承,不必创建构造函数
缺点
与原型链中提到的缺点相同,一个是传参的问题,一个是属性共享的问题。
//第一种
function createObject(obj) {
function Fn() {};
Fn.prototype = obj;
return new Fun();
}
//第二种
//Object.create() 是把现有对象的属性,挂到新建对象的原型上,新建对象为空对象
//ECMAScript 5通过增加Object.create()方法将原型式继承的概念规范化了。
//这个方法接收两个参数:作为新对象原型的对象,以及给新对象定义额外属性的对象(第二个可选)。
//在只有一个参数时,Object.create()与这里的函数A方法效果相同。
let child = Object.create(obj)
5.寄生式继承
寄生式继承的思路是创建一个用于封装继承过程的函数,通过传入一个对象,然后复制一个对象的副本,然后对象进行扩展,最后返回这个对象。这个扩展的过程就可以理解是一种继承。这种继承的优点就是对一个简单对象实现继承,如果这个对象不是我们的自定义类型时。缺点是没有办法实现函数的复用。
优点
在主要考虑对象而不是自定义类型和构造函数的情况下,实现简单的继承。
缺点
使用该继承方式,在为对象添加函数的时候,没有办法做到函数的复用。
function createFactory(obj){
var clone = Object.create(obj); //通过调用函数创建一个新对象
clone.say = function(){ // 某种方式增强这个对象
console.log("say");
}
return clone; // 返回这个对象
}
6.寄生式组合继承
组合继承的缺点就是使用超类型的实例做为子类型的原型,导致添加了不必要的原型属性。寄生式组合继承的方式是使用超类型的原型的副本来作为子类型的原型,这样就避免了创建不必要的属性。
优点
效率高,避免了在 SubType.prototype 上创建不必要的属性。与此同时还能保持原型链不变,开发人员普遍认为寄生组合式继承是引用类型最理想的继承范式。
function inheritPrototype(Child, Parent){
var prototype = Object.create(Parent.prototype); // 创建原型对象是超类原型对象的一个实例对象
prototype.constructor = Child; // 弥补因为重写原型而失去的默认的 constructor 属性。
Child.prototype = prototype; // 实现原型继承
}
es6 继承
extends
class ChildClass extends ParentClass { ... }