白话讲解JavaScript继承

首先我们要知道继承是要做什么的, 是为了节省内存消耗, 避免重复调用问题

warning本篇文章建立在已经有所了解JavaScript继承的情况下去进行进一步梳理(原创)


简述

并且既然叫做JavaScript继承, 那么这几个问题都是围绕怎样实现继承

用抄袭试卷的方式来讲解,

原型相当于答案的最开始来源处

constructor相当于最后的签名 你总不能把别人的名字一起抄上去吧, 这代表签名, 这份试卷是你自己的

如果我要实时了解你的试卷, 那我就要指定原型是你, 相当于构建一个单向偷窥隧道

当然如果也有其他人偷窥你的试卷, 那么我和那个人就是共享原型, 原型是你的试卷


1. 构造函数继承

(继承构造函数), 也叫类抄写, 比如我们在考试, 你写了一个构造函数, 我要继承你的构造函数, 就在我的构造函数里面用call或者cpply抄写一份你的东西, 我给你题目你给我答案, 当然我抄完后还可以在自己的构造函数的选做题里面放一些自己的东西

因为我只是抄了你的东西, 但是我们并不是公用一份, 所以, 我们两个构造函数是独立的

缺点是, 因为不是共享, 是一次性拷贝, 也就是如果你后面修改了你的答案我是不知道的, 除非我再抄你一遍


2. 原型链继承

也叫类继承(也是继承构造函数), 最简单的继承, 比如老大是原型, 你是二当家, 其他人都是小弟都叫实例继承了二当家, 当然默认也是继承了老大, 我们这个帮派一旦老大或者二当家有政策发布, 下面的小弟都要修改

这就是原型链继承,

缺点是, 上级改动, 下级都要跟着修改


3. 组合继承

(继承构造函数), 什么意思, 我们在构造函数基础的基础上再进行讲述

我还是要抄你试卷, 首先我还是要全抄!!!, 因为你是学霸

但是我不想只抄一遍, 你有些大题改了我也要知道, 所以你就把你的试卷分成两部分, 一部分是给我给你题目你给我对于的答案, 这部分放在构造函数内, 你可能要修改的部分改了要告诉我, 你就把答案放在你的原型里面你改了我也改

当然我也可以有自己的想法, 可以加一些自己的答案

缺点: 调用了两次父类构造函数, 耗费内存, 第一次是让你帮我做题, new一个你的构造函数返回给我, 目的是为了成为你的实例好去引用你的原型

使用 new 操作符调用了一次 构造函数

有方法避免多次调用直接去掉 new 操作符

写成 Child.prototype = Parent.prototype

但是这样并不好,虽然避免出现重复调用但导致修改子类 constructor 的时候父类也被修改了, 也就是如果我再试卷上签了自己的名字那么意味着你的原型的构造者不在是你的构造函数, 而是我的了

这是组合式继承的唯一缺点


4. 原型式继承(继承对象) ———————注意是对象

用es5的object.create(对象)返回一个实例给我抄

原理是浅拷贝

我直接抄袭你的对象, 我不想改, 没有想法

抄袭对象的话不用签名的, 也就是不用constructor


5. 寄生式继承(继承对象)———————注意是对象

原型式继承的基础上为子类增加属性和方法, 就是继承了对方也添加了自己的方法


6. 寄生组合式继承

解决了之前组合继承的两次调用父类构造函数问题

那么第一次调用父类构造函数是不可避免的, 就是parent.call(this)这个是不可省略的

要精简的是组合式继承的第二次通过调用new Parent()想办法来解决这次的调用

之前说过不用new,改用parent.prototype来公用同一个原型是不合理的

因为如果我的原型的constructor指向了我自己的构造函就会导致原型的constructor也会改成我的构造函数, 就不合理了, 因为原型的构造函数还是要指向我的父类的

那么就可以用到原型式继承的解决方案来解决, 即在原型中间新建一个空的构造函数作为中介, 然后如果我执行child.prototype.constructor=child就不会影响parent.constructor指向我会变成空构造函数的构造者变成了我

image-20190527211752570

从而解决了问题

7. es6的calss继承(推荐使用)

挺优秀的方式, 推荐使用, 语法很清晰

class Parent {
    constructor(name, friends) { // 该属性在构造函数上,不共享
        this.name = name
        this.friends = friends
    }
    log() { // 该方法在原型上,共享
        return this
    }
}
Parent.prototype.share = [1, 2, 3] // 原型上的属性,共享

class Child extends Parent {
    constructor(name, friends, gender) {
        super(name, friends) // 继承父类构造函数
        this.gender = gender
    }
}

你可能感兴趣的:(白话讲解JavaScript继承)