当前位置: 移动技术网 > IT编程>开发语言>JavaScript > JavaScript实现继承(七种)

JavaScript实现继承(七种)

2020年07月24日  | 移动技术网IT编程  | 我要评论

Js继承

在学习继承前希望读者先去学习下js原型和原型对象的知识。
对于js原型和原型对象的理解

原型链继承

让一个函数的原型指向另一个引用类型的对象,这个对象中又有指针是指向另一个引用类型的原型对象的,原型对象也可以继续指下去,直到原型链的末端

function Animal(){
    this.name='动物'
}
Animal.prototype.say=function(){
    return this.name
}
function Cat(){
    this.name='猫'
}
Cat.prototype=new Animal()
let c=new Cat()
c.say()   //猫
//可以看到Cat继承了say这个方法

这里的Cat的prototype指向了Animal的实例,而Animal的实例的属性_proto_指向了Animal.prototype,Animal.prototype的constructor又指向了Animal构造函数,这就是构成了一条原型链,原型链到这里其实还没有结束,因为我们知道所有的对象都是继承Object的,所以

Animal.prototype._proto_==Object.prototype //true
Object.prototype._proto_==Object  //true

这样就构成了一个完整的原型链,这边要注意的是所有函数的原始原型对象都是指向Object原型对象的。原型链的末端就是Object.prototype
如图所示:
红色线条就构成了一条原型链
在这里插入图片描述

原型链的特点就是它既是子类的实例也是父类的实例,且如果继承的对象中是个引用类型的,那么这将会被所有实例全部引用一个引用类型的数据,原型链继承一般也很少使用。

c instanceof Animal //true
c instanceof Cat    //true

构造函数继承

这个方法其实很简单,就是通过call或者是apply在一个构造函数中执行一下另一个构造函数即可。

function Animal(){
    this.type=['狗','猪']
}
function Cat(){
    Animal.call(this)
}
let c=new Cat()
c.type.push('猫')
c.type //['狗','猪','猫']
//可以看到Cat继承了Animal的type属性。

构造函数继承中不存在函数复用,所有都是借用构造函数来初始化的,所以我们也很少用

组合继承

组合继承顾名思义,就是将原型链继承和构造函数继承放在一块来实现。

function Animal(name){
    this.name=name
}
Animal.prototype.say=function(){
    console.log('--动物--')
}
function Cat(name){
    Animal.call(this,name)
}
Cat.prototype=new Animal()
Cat.prototype.constructor=Cat
let c=new Cat('猫')
c.name//猫
c.say() //--动物--

组合继承最大的缺点就是它会调用两次父类的构造函数。

原型式继承

最开始原型式的继承提出方案是这个样子的

function object(obj){
    function f(){}
    f.prototype=obj
    let F=new f()
    return F
}
let people={name:'姓名'}
let p=new object(people)
p.name //姓名

object函数接受一个对象 然后在函数里面声明一个局部的构造函数,让其原型指向传过来的参数,然后实例化并返回就可

ECMAScript5规范化了原型式继承,即Object.create接收两个参数,一个是用作新对象原型的对象和一个新对象作为额外的属性

let Animal={name:'动物'}
let Cat=Object.create(Animal)
Cat.name //动物

只是一个对象要类似于另一个对象,这是完全可以胜任的,要注意的就是引用类型的继承还是会共享相应的值。

寄生式继承

与原型式基本类似,只不过函数中创建对象的方式不同 ,他只考虑最基本的

function create(obj){
    let clone=object(obj)  //调用原型式的函数
    clone.say=function(){
        console.log('说话')
    }
    return clone
}
let p={name:'姓名'}
let o=create(p)
o.name// 姓名
o.say// 说话

如果只考虑最基本的对象而不考虑通过构造函数来生成对象的话,寄生式继承也是一种好的方式

寄生组合继承

在介绍寄生组合前我们先来看下组合继承的两次生成实例。

function Animal(){
    this.name='动物'
}
function Cat(){
    Animal.call(this) //第二次调用
}
Cat.prototype=new Animal() //第一次调用
Cat.Prototype.constructor=Cat
let c=new Cat()  

我们可以看到组合继承调用了两次父类的构造函数,第二次调用会使得原型中的属性被实例中的同名属性所覆盖,因此要解决这个问题,就有了寄生组合继承,其实就是在定义子类的原型时不去new父类,我们只要一开始的时候获取到父类的原型对象的副本即可

function Animal(){
    this.name='动物'
}
function Cat(){
    Animal.call(this) //只有这一次执行
}
let o=Object.create(Animal.prototype)//获取一个父类原型的副本
Cat.prototype=o
Cat.prototype.constructor=Cat
let c=new Cat()
c.name //动物

es6中的继承

es6中新增了class extends关键字,让js具有了与其他OO语言一样的对象写法

class A{
    constructor(){
        console.log('aaa')
        this.a='a'
    }
}
class B extends A{
    constructor(){
        super()
        console.log('bbb')
        this.b='b'
    }
}
let b=new B()
b.a //'a'
b.b //'b'

本文地址:https://blog.csdn.net/qq_40026070/article/details/107543389

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网