总结归纳了6种js的继承实现方式并分析了其中实现的区别,为了解释,定义一个作为的父类的类型Animal,之后定义的类都为Animal类的子类,实现方式不同,Animal类代码如下:
function Animal(name) {
this.name = name;
this.color = 'blue';
}
Animal.prototype.sayName = function () {
console.log(this.name);
};
复制代码
1 简单的原型链继承方式
这种是最简单的实现继承的方式,即使子类的原型对象等于父类的一个新的实例对象,举例代码如下:
// 1.原型链继承
function Cat() {
}
Cat.prototype = new Animal();
复制代码
这样即实现了Cat类对Animal类的继承,其中存在的问题是Cat的原型对象中会有Animal类的构造函数中的属性如上例中的color属性,而这个属性是不必要的。而且Cat.prototype的constructor属性也是指向Animal的。实现继承后关系如图所示:
2 借用构造函数继承
借用构造函数继承也叫伪造对象继承或者经典继承,其主要实现方式是在子类的构造函数中调用父类的构造函数,示例代码如下:
// 2.借用构造函数,经典继承
function Dog() {
// 继承Animal,并传递参数
Animal.call(this, 'doge');
}
var instance = new Dog();
复制代码
这种方式的好处是可以向父类传递参数,而且父类的原型对象中的属性及方法对子类型也是不可见的,所以这种方法很少单独使用。
3 组合继承
这种继承的方式结合了借用构造函数继承和简单的原型链继承,示例代码如下:
// 3.组合继承
function Mouse() {
Animal.call(this, 'jerry');
}
// 继承方法
Mouse.prototype = new Animal();
Mouse.constructor = Mouse;
复制代码
这种继承方式是js中最常用的继承模式,但是其中仍然没有解决原型链继承问题中存在的子类原型对象中存在父类构造函数中属性的问题。
4 原型式继承
这种继承方式主要针对与不关注自定义类型和构造函数而考虑对象的情况下,思路是基于已有的对象创建新对象,实例代码如下:
// 4.原型式继承
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
var bird1 = object(Animal);
复制代码
这种继承方式通过临时创建一个新的构造函数F并将其原型对象设为所需要的对象,然后返回一个此构造函数F的实例以实现继承。关系图如下:
Object.create()
规范化了原型式继承,上面的代码可以改为:
var bird2 = Object.create(Animal, {number: {value: 3}});
复制代码
同时在Object.create()
中可以在第二参数中实现定义额外的属性,bird2相对bird1多了一个value属性。在只有一个参数时上方定义的object()函数和Object.create()函数行为相同。
5 寄生式继承
这种继承方式使用了Object.create()
,创建一个用于封装继承过程的函数,在函数内部来增强对象,其本质原理与原型式继承类似,示例代码:
// 5.寄生式继承
function createAnother(original) {
var clone = Object.create(original);
clone.sayHi = function () {
console.log('hi');
};
return clone;
}
var anotherAnimal = createAnother(Animal);
anotherAnimal.sayHi();
复制代码
6 寄生组合式继承
寄生组合式继承是最理想的继承范式,通过借用构造函数来继承属性,通过原型链来继承方法。本质上使用了寄生式继承来继承超类型的原型,然后将结果指定给子类型的原型。实例代码如下:
// 6.寄生组合式继承
function inheritPrototype(subType, superType) {
// 创建对象
var prototype = Object.create(superType.prototype);
// 增强对象
prototype.constructor = subType;
// 指定对象
subType.prototype = prototype;
}
function Fish(name) {
Animal.call(this, 'fish');
}
inheritPrototype(Fish, Animal);
复制代码
使用结果示意图如下: