Javascript五大继承方式

193 阅读3分钟

Javascript作为面向对象的弱类型语言,继承也是它非常强大的特性之一。每每我们和面试官聊到JS中的原型原型链,我们就很可能不可避免地聊到继承,为了更好地和面试官唠嗑呢,或者说为了更好地理解JS的特征,继承都是我们一定要弄明白的。什么是继承?我们在JS中如何实现继承呢?本文章列出了JS中的五种非常经典的继承方式

Javasciprt五大经典继承

1. 原型链继承

2. 构造函数继承

3. 组合继承

4. 寄生组合继承

5. class继承

1.原型链继承

/* 原型链继承实现开始 */

function Animal(name){
	this.name = name
	this.loveFood = ['apple','banana','potatoes']
}

Animal.prototype.sayLoveFood = function(){
	console.log(this.loveFood)
}

function Dog(){}

Dog.prototype = new Animal()

/* 原型链继承结束 */




/* 以下是例子 说明原型链继承的缺点(实例的引用类型共用了)*/
var dog1 = new Dog()
var dog2 = new Dog()

dog1.loveFood.push('asd')
console.log(dog2.sayLoveFood())

打开控制台粘贴复制可以得出原型链继承的用例结果

1.png

优点

  • 容易实现
  • 纯粹的继承关系,创建的实例是子类的实例也是父类的实例
  • 父类的原型方法、原型属性子类都能访问到

缺点 :

  • 原型对象的所有属性被所有实例共享了,引用类型共用了(最大缺点)。
  • 无法实现多继承(毕竟Dog.prototype只有一个)
  • 创建子类实例时,无法向父类构造参数传参

2.构造函数继承

/* 构造函数继承开始 */

function Animal(name){
	this.name = name
	this.loveFood = ['apple','banana','potatoes']
}

Animal.prototype.sayLoveFood = function(){
	console.log(this.loveFood)
}

function Dog(name){
	Animal.call(this,name)
}

/* 构造函数继承结束 */

/* 以下是例子 说明构造函数继承的缺点 */
var dog1 = new Dog()
dog1.sayLoveFood()

打开控制台粘贴复制可以得出构造函数继承的用例结果

2.png

优点 :

  • 可以实现多继承,在Dog构造函数用多次call继承需要继承的父类就好了
  • 实例的引用类型不是共享的了

缺点 :

  • 若是父类的函数不是定义在原型上的,那么创建实例的函数不是复用的
  • 实例不是父类的实例
  • 实例不能继承父类的原型属性/方法(最大缺点)

3.组合继承

/* 组合继承开始 */

function Animal(name){
	this.name = name
	this.loveFood = ['apple','banana','potatoes']
}

Animal.prototype.sayLoveFood = function(){
	console.log(this.loveFood)
}

function Dog(name){
	Animal.call(this,name)
}

Dog.prototype = new Animal()
Dog.prototype.constructor = Dog

/* 组合继承结束 */

优点:

  • 可以实现多继承
  • 子类是父类的实例
  • 把函数定义在父类的的原型上,函数就可以复用了
  • 实例从父类继承的引用类型也不会共享 可以说是挺完美了

缺点:

  • 创建实例的时候父类构造函数被调用了两次(一次是call调用,一次是new Animal调用)

4.寄生组合式继承

/* 寄生组合式继承开始 */
function Animal(name){
	this.name = name
	this.loveFood = ['apple','banana','potatoes']
}

Animal.prototype.sayLoveFood = function(){
	console.log(this.loveFood)
}

var f = function(){}
f.prototype = Animal.prototype

function Dog(name){
	Animal.call(this,name)
}

Dog.prototype = new f()
Dog.prototype.constructor = Dog
/* 寄生组合式继承结束 */

实现原理:其实并不难,跟组合式继承差不多,只是多定义了一个函数f,把父类的prototype继承下来(为了把父类不在原型上的属性砍掉),这样后面子类继承的时候就不会调用两次父类构造函数了。

优点: 可以说是完美了,该有的都有了

缺点: 多定义了一个函数

5.class实现继承

class Animal {
    constructor(name) {
        this.name = name
    } 
    getName() {
        return this.name
    }
}
class Dog extends Animal {
    constructor(name, age) {
        super(name)
        this.age = age
    }
}

var dog = new Dog('a',15)
console.log(dog.getName())

优点 : class其实只是用ES5的prototype实现继承的一个语法糖而已,但是class让继承结构更清晰了

缺点 : 无

更多class相关的内容可以参考阮一峰老师的ES6入门: es6.ruanyifeng.com/#docs/class

完结

以上就是javascript的五大经典继承拉,你学会了吗?欢迎点赞加收藏!!!

你们的支持是我创作最大的动力。