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

  

业务场景

  原型与原型链,从作用上来说,理解它在当前时代用处其实不大,因为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. SQL 数字转为中文大写

    USE [SPECIAL_BLD]GO SET ANSI_NULLS ONGO SET QUOTED_IDENTIFIER ONGO CREATE FUNCTION [dbo].[get_upper] ...

  2. 5G,仅仅是更快的网速吗?

    前不久参加了华为的Dev Summit 2020开发者大会,听到了关于5G的一些分享,刚好最近对5G有一些自己的思考,在此分享给大家. 什么是5G 在这里我不想列举各种晦涩难懂的术语,简单说来,5G就 ...

  3. 洛谷 3111 [USACO14DEC]牛慢跑Cow Jog_Sliver 题解

    本蒟蒻又来发题解了, 一道较水的模拟题. 题意不过多解释, 思路如下: 在最开始的时候求出每头牛在t秒的位置(最终位置 然后,如果后一头牛追上了前一头牛,那就无视它, 把它们看成一个整体. else ...

  4. iOS本地数据存储

    http://www.jianshu.com/p/a3eeae99e902 大牛整理的超全

  5. Ceph 集群搭建

    1.Ceph部署 1.1 Ceph 安装前准备,环境与拓扑图如下: 主机名 外网IP 内网IP 安装组件 磁盘块 c720181 172.22.69.84 192.168.20.181 ceph-de ...

  6. Django开发登录功能实战

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理.作者:凡夫俗子66 Django 如果是定义函数写登录路由,需要判断请求方法 ...

  7. CyAPI环境搭建

    http://jingyan.baidu.com/article/e6c8503c0690cee54f1a1893.html

  8. 【重温基础】16.JSON对象介绍

    本文是 重温基础 系列文章的第十六篇. 今日感受:静. 系列目录: [复习资料]ES6/ES7/ES8/ES9资料整理(个人整理) [重温基础]1-14篇 [重温基础]15.JS对象介绍 本章节复习的 ...

  9. jmeter微信公众号接口测试实例

    线程组 HTTP Cookie 管理器 HTTP 请求默认值 用户定义的变量 察看结果树 HTTP请求 响应断言 正则表达式提取器 线程组 HTTP Cookie 管理器 HTTP 请求默认值 用户定 ...

  10. Vue项目中实现用户登录及token验证

    学习博客:https://www.cnblogs.com/web-record/p/9876916.html