关于这部分我看过大量的文章,数不胜数,包括阮一峰的继承三部曲,还有各种慕课的视频教程,网上无数继承方法的对比。也对很多概念存在长期错误的理解。今天做一个正确的总结,用来给原型链和继承这块知识画上句号,而从深度上来说,则是深入到堆内存中去一探究竟。

  

业务场景

  原型与原型链,从作用上来说,理解它在当前时代用处其实不大,因为ES6的普及,封装的class语法糖让人们很难想再去翻构造函数、原型链这些历史旧账。而且ES6的class除了不支持IE、黑莓这种复古浏览器,主流的现代浏览器都已得到了全面支持。而且再不济,要去兼容IE,也有babel来帮我们转译class语法,用不着去手写prototype,__proto__等关系。

  所以研究原型链的作用到底在哪儿呢?我认为它的作用在于从知识层面帮我们看清楚extends和super的本质。至于在业务层面,它并没有任何作用。

原理阐述

  首先,prototype属性是函数独有的,它指向一个堆内存中的对象,这个对象就叫原型对象。

  原型对象有很多个,每个构造函数都对应着一个原型对象;

  当函数作为构造函数使用,也就是实例化时,它会把这个原型对象的指针命名为__proto__,并强加到实例化对象中。这样一来,某个构造函数的prototype属性和通过这个构造函数实例化的所有对象的__proto__属性,都指向某一个原型对象。

  所谓原型链,就是将堆内存中不同的原型对象串起来,那怎么让这些分散在不同堆内存的,毫不相关的原型对象串起来呢?

  答案就是:引用。因为原型对象也是一个对象,它也有__proto__属性,所以,只要让一个某个原型对象的__proto__属性,指向另外一个原型对象。这样就在毫不相关的两个原型对象之间打通了关系。换言之,这样就实现了继承。

画图理解

  

  在上图中,原型对象1和原型对象2的__proto__属性都默认指向根原型对象。如果要使原型对象1继承原型对象2,则把原型对象1的默认指向根原型对象的__proto__属性,改为指向原型对象2。(灰色箭头转为蓝色虚线箭头)

  当然,为了不使这副图变得混乱,我没有把一个东西画出来,那就是原型对象的constructor属性指向其构造函数,也就是说,一个构造函数可以通过prototype属性找到其对应的原型对象,一个原型对象也可以通过自身的constructor属性找到其对应的构造函数,这也侧面印证了:在堆内存中的原型对象是很多的。

  

  

ES6的语法糖分析

  在ES6中,定义了类,extends和super。它们的本来面目如下:

  假设有类A和类B,定义class A extends B。且在类A的constructor构造函数中调用了super函数,实现了类A对类B的继承。

  ES6中的类就是构造函数,extends在这里表示A.prototype.__proto__ = B.prototype。而super则是ES5中的A.call(this,args)。args表示A中传入的实例化参数。

  关于super,你写不写都可以。如果你要在子类定义一个constructor,且constructor里面要用到this,那么super就是必写的,且需要写在this出现之前;如果不是我刚刚提到的这种情况,那么可以不写;

代码验证

  我们敲出一系列代码来验证我的总结:

  

  (验证一:原型链图,通过)

  

(验证2:ES6语法糖,通过)

【JS档案揭秘】第三集 深入最底层探秘原型链的更多相关文章

  1. 【JS档案揭秘】第二集 Event loop与执行栈

    我时常在思考关于JS的很多知识在工作中有什么用?是否只能存在于面试这种理论性的东西中,对于我们的业务和工作,它们又能扮演怎样的角色.以后在JS档案揭秘的每一期里,都会加入我对于业务的思考,让这些知识不 ...

  2. 【JS档案揭秘】第一集 内存泄漏与垃圾回收

    程序的运行需要内存,对于一些需要持续运行很久的程序,尤其是服务器进程,如果不及时释放掉不再需要的内存,就会导致内存堆中的占用持续走高,最终可能导致程序崩溃. 不再需要使用的内存,却一直占用着空间,得不 ...

  3. JS function 是函数也是对象, 浅谈原型链

    JS function 是函数也是对象, 浅谈原型链 JS 唯一支持的继承方式是通过原型链继承, 理解好原型链非常重要, 我记录下我的理解 1. 前言 new 出来的实例有 _proto_ 属性, 并 ...

  4. 【JS档案揭秘】第四集 关于this的讨论到此为止

    网上关于this的指向问题的博客文章很多,但大多数都是复制粘贴,也不能用简洁的语言讲清楚,而是不停地写一些示例,看得人云里雾里. 这一集,我只给出结论,以及判定的通用方法,至于是否确实如我所讲,大家可 ...

  5. 关于js的几道经典题(作用域、原型链等)自己做的

    1. function test() { var a = 1; setTimeout(function() { alert(a); a = 3; }, 1000); a = 2; setTimeout ...

  6. JS学习笔记——JavaScript继承的6种方法(原型链、借用构造函数、组合、原型式、寄生式、寄生组合式)

    JavaScript继承的6种方法 1,原型链继承 2,借用构造函数继承 3,组合继承(原型+借用构造) 4,原型式继承 5,寄生式继承 6,寄生组合式继承 1.原型链继承. <script t ...

  7. 【js基础修炼之路】— 我理解的原型链

    提起原型链,大家并不陌生,但是对于新人来说一提到原型方面的东西就会比较懵.在我自一次面试的时候,面试官也给我提了这样的问题,当时就按照我的理解说了一些,但是很肤浅,在此我希望给刚入门的前端小伙伴聊一下 ...

  8. 三张图理解JavaScript原型链

  9. JS原型与原型链(好文看三遍)

    一. 普通对象与函数对象 JavaScript 中,万物皆对象!但对象也是有区别的.分为普通对象和函数对象,Object ,Function 是JS自带的函数对象. 下面举例说明: function ...

随机推荐

  1. golang数据结构之循环链表

    循环链表还是挺有难度的: 向链表中插入第一条数据的时候如何进行初始化. 删除循环链表中的数据时要考虑多种情况. 详情在代码中一一说明. 目录结构如下: circleLink.go package li ...

  2. 大型情感剧集Selenium:3_元素定位 #华为云·寻找黑马程序员#

    关于昨天的文章 今天有朋友反馈,代码运行的时候,selenium提示警告 DeprecationWarning: use options instead of chrome_options drive ...

  3. 17.Django学习之django自带的contentType表

    通过django的contentType表来搞定一个表里面有多个外键的简单处理: 摘自:https://blog.csdn.net/aaronthon/article/details/81714496 ...

  4. [TimLinux] myblog 创建第一个app

    1. 项目结构 项目地址:https://github.com/timscm/myblog.git 2. 启动项目 通过pycharm启动项目,进入调试模式: "D:\Program Fil ...

  5. vs2017/vs2019 去掉 单击aspx文件预览页面

    初次安装vs2017或者vs2019,新建的项目中,每次单击项目文件时,文件自动打开了 然后 打开 工具->选项->环境->选项卡和窗口->预览选项卡->勾掉" ...

  6. asp.net core 配置微信返回信息接口

    这玩意弄了两天 微信的API需要升级了 只有一份PHP的DEMO 还有个坑 返回值一定要是 微信传入的echostr 否则 出现配置失败,这个问题耗了我俩小时 最后还是在论坛看到的解决方案. 项目必须 ...

  7. 如何成为一名成功的iOS程序员,挑战年薪50万?

    编程是一个仅靠兴趣仍不足以抵达成功彼岸的领域.你必须充满激情,并且持之以恒地不断汲取更多有关编程的知识.只是对编程感兴趣还不足以功成名就——众所周知,我们工作起来像疯子. 编程是一个没有极限的职业,所 ...

  8. JS基础-全局内置对象

    对象 JS中有那些内置对象 数据封装类对象 String.Array.Object.Boolean.Number 其他对象 Math.Date.RegExp.Error.Function.Argume ...

  9. 【Spring MVC】Properties文件的加载

    [Spring MVC]Properties文件的加载 转载:https://www.cnblogs.com/yangchongxing/p/10726885.html 参考:https://java ...

  10. 【Java Web开发学习】Spring MVC文件上传

    [Java Web开发学习]Spring MVC文件上传 转载:https://www.cnblogs.com/yangchongxing/p/9290489.html 文件上传有两种实现方式,都比较 ...