温故知新(一)图解原型链继承

近日学习如何写JS插件,难点一是功能,二是语法。在实践中发现对于原型链的理解有些遗忘,于是重新学习一遍。

原型链继承:如何将链1改造为链2

链1: new PrimaryStudent() ----> PrimaryStudent.prototype ----> Object.prototype ----> null
链2: new PrimaryStudent() ----> PrimaryStudent.prototype ----> Student.prototype ----> Object.prototype ----> null

在实践中用到的两个类:

在以上的声明步骤中,仅仅是使PrimaryStudent类获得了与Student类相同的属性, 两者在原型链上还是毫无关系的

接下来就是要绑定原型链了。

目标是从【原型链一】变成【原型链二】

我们分几种情况来讨论:

PrimaryStudent.prototype = Student.prototype;

乍一看好像真的没有问题哇,试试看就知道问题出在哪里了。

出现问题
明明只想给子类PrimaryStudent添加一个bye的方法,结果Student也有了。

原因分析
语句(1)看似生成单向指向→ (PrimaryStudent的原型 → Student的原型),但实际形成了双向绑定。这就导致了primaryStudent与Student共享一个原型对象,primaryStudent类不能添加自己私有的新方法。primaryStudent原型添加新方法时,会同时修改Student的原型。

错误总结
原型链的重要作用就是,保证单向的传递(从父类到子类),不能反向修改(子类修改父类)。

根据上一种方法,我们可以得出,要实现原型链的正确拼接,意味着要 切断双向传递 ,并且 保证单向传递的动态性 ,即父类的变化可以体现在子类中但子类的变化与父类无关。
使用一个过桥空函数F,完成原型链的拼接。

在这个实践中,F函数起到的作用是,通过“语句(2)双向绑定”+“语句(3)单向传递”,实现了我们的目标效果“父类到子类的单向传递”。

我们来测试一下看看会不会有什么问题。

原因分析

方法封装
过桥函数F所起的作用,是可以被封装起来的。

在实践验证第二种方法的过程中,发现new操作符的神奇作用,于是有一个新想法:既然new可以单向,那么用new来单向连接sutdent会发生什么?
PrimaryStudent.prototype = new Student();
检验一下

出现问题
: ) 这就相当尴尬了,这条 PrimaryStudent.prototype = new Student(); 语句的实现效果与利用过桥函数F的效果是相同的。所以空函数F的用与不用,有什么不同呢?

问题总结
看了原教程下面的讨论区,大家一致的意见都是, 两种方法都可以实现目标效果,但是使用过桥函数F,可以清空构造函数里的属性,避免污染,造成原型对象的膨胀

在方法二中,我们使用空函数F,获得了一个干净的原型对象;
在方法三中,我们便利地实现了原型链绑定;
有没有什么办法可以取两者优点?
操作如下:
PrimaryStudent.prototype = Object.create(Student.prototype) ;

原因分析
Object.create(Student.prototype),创建了一个干净的原型对象,其包含了Student原型对象的属性与方法,但并不通过构造函数去调用它,因此可以省去构造函数执行时的属性赋值(污染)。
这一方法也就是class语法糖的原理。

方法改进
通过上述操作,当前的 PrimaryStudent.prototype.constructor === Student ;这个属性并不会影响我们的实际使用。
但是在大部分的情况下,我们还是有必要修正一下PrimaryStudent.prototype.constructor属性,使 PrimaryStudent.prototype.constructor === PrimaryStudent 。

出现问题
那么 修正constructor属性的意义在于什么? ,这是我当时比较困惑的一点,在偶然间看见一篇博客,解答了我的困惑: 为什么要做A.prototype.constructor=A这样的修正?

一般情况,我们都通过new Foo()来实例化对象,它实际调用的是Foo构造函数本身,而不是Foo.prototype.constructor,因此constructor属性的指向不会造成影响。
但是当我们显式调用Foo.prototype.constructor来实例化对象时,情况就不同了。而对于constructor属性的修正,也正是为了避免这一情况下的出错。

个人比较喜欢看图学习,为了方便理解,对于学习过程中出现的几个结果,进行画图分析,其中红色箭头流代表原型链。绘图结构,参考了高程三中的继承章节。

大概是学习原型链的第三次了,感觉自己是个理解能力十分菜的人,看不懂与学了就忘两种情况贯穿于每一次的学习过程,最近又进入了准备面试的阶段,去年没有好好把握秋招,一点准备都没有地乱投简历,今年寒假要好好储备一下,争取春招时候卖个好人家QAQ 一定要提前做好准备拒绝拖延

距离上一次的技术文档已经过去了三个月,相当不自觉(!)最近的规划是学习高程三,目标是多输出多输出多输出,一定要多写笔记。



  • 娓╂晠鐭ユ柊(涓)鍥捐В鍘熷瀷閾剧户鎵
    绛旓細鍘熷瀷閾剧户鎵锛氬浣曞皢閾1鏀归犱负閾2 閾1锛 new PrimaryStudent() ---> PrimaryStudent.prototype ---> Object.prototype ---> null 閾2锛 new PrimaryStudent() ---> PrimaryStudent.prototype ---> Student.prototype ---> Object.prototype ---> null 鍦ㄥ疄璺典腑鐢ㄥ埌鐨勪袱涓被锛氬湪浠ヤ笂鐨勫0鏄...
  • 扩展阅读:温故而知新对下联 ... 温故知新代表什么生肖 ... 温故知新打一正确生肖 ... 乡遇故知唯美句子 ... 温故而知新顺向正迁移 ... 与温故知新相近的诗句 ... 温故知新打一动物 ... 论语有云温故知新 ... 原型和原型链的理解面试题 ...

    本站交流只代表网友个人观点,与本站立场无关
    欢迎反馈与建议,请联系电邮
    2024© 车视网