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

  

业务场景

  原型与原型链,从作用上来说,理解它在当前时代用处其实不大,因为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. oracle监听查看、启动和停止

    oracle监听查看.启动和停止 查看监听lsnrctl status 停止监听lsnrctl stop 启动监听lsnrctl start

  2. redis位图巧用,节约内存

    最近要做一个圣诞抽奖活动,需要记录每天用户签到的记录,以前一般都是用普通的字符串数据类型,每个用户的签到用一个 key // 用户10在活动第一天的签到key为record:1:10 $key = & ...

  3. iOS 音频开发之CoreAudio

    转自:http://www.cnblogs.com/javawebsoa/archive/2013/05/20/3089511.html 接 触过IOS音频开发的同学都知道,Core Audio 是I ...

  4. MongoDB下载+安装+运行

    一. 官网下载安装 MongoDB 提供了 OSX 平台上 64 位的安装包,你可以在官网下载安装包. 下载地址:MongoDB官网-Community Server 选择适合自己平台的版本, 下载对 ...

  5. CF 1131A,1131B,1131C,1131D,1131F(Round541 A,B,C,D,F)题解

    A. Sea Battle time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  6. CSU OJ2151 集训难度

    小L正在组织acm暑假集训,但众所周知,暑假集训的萌新中有OI神犇,也有暑假才开始学算法的萌新,如果统一集训的难度,无法很好地让萌新们得到训练,所以小L想了一个办法,根据每次测试的情况,改变萌新们的集 ...

  7. 模拟实现 Promise(小白版)

    模拟实现 Promise(小白版) 本篇来讲讲如何模拟实现一个 Promise 的基本功能,网上这类文章已经很多,本篇笔墨会比较多,因为想用自己的理解,用白话文来讲讲 Promise 的基本规范,参考 ...

  8. [状态模式]实现stopwatch

    1.模拟传统面向对象语言的状态模式实现 // Stopwatch类 状态机class Stopwatch {    constructor() {        this.button1 = null ...

  9. hdu 1255 覆盖的面积 (扫描线求矩形交)

    覆盖的面积 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  10. 微信小程序 wepy框架 之拦截器intercepter使用

    1,在使用wepy框架创建的项目下 找到src/app.wpy 2,在app.wpy constructor方法中添加 super(); this.use('promisify');//启用ES6 p ...