原形链是JS难点之一,而且很多书都喜欢用一大堆的文字解释给你听什么什么是原型链,就算有图配上讲解,有的图也是点到为止,很难让人不产生疑惑。

我们先来看一段程序,友情提示sublimeText看更爽:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>《JavaScript高级程序设计(第三版)》Page163页的源码</title>
<link href="" rel="stylesheet">
</head>
<body>
<script type="text/javascript">
function SuperType(){
this.property = "我是父亲的属性";
}
SuperType.prototype.getSuperValue = function(){
return this.property;
}
function SubType(){
this.subproperty = "我是孩子的属性";
}
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function(){
return this.subproperty;
}
var instance = new SubType();  
alert(instance.getSuperValue());//我是父亲的属性
</script>
</body>
</html>

有的人可能会觉得很熟悉,这是《JavaScript高级程序设计(第三版)》Page163页的源码。ps:将原来的false,true改成中文字符串比较容易看懂

但是下面的图我看了就觉得很怪了,原来的原型不是换了吗?怎么还指向呢?然后自己画了一个图并且证明了一遍,才发现原来书里画的也是错的。


然后就引出了想要图解原型链的想法,我们来看下面,友情提示sublimeText看更爽:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>JS原形链图解</title>
</head>
<body>
<script type="text/javascript">
function SuperType(){
this.property = "我是父亲的属性";
}
SuperType.prototype.getSuperValue = function(){
return this.property;
}
function SubType(){
this.subproperty = "我是孩子的属性";
}
var SubPro = SubType.prototype;//因为下面要改变原型,先用一个引用存起来,不然等下找不到
console.log("没改变原型之前是相等的:"+(SubType.prototype===SubPro))
SubType.prototype = new SuperType(); //这里改变了SubType的原型使它指向一个SuperType实例
console.log("给SubType构造函数换了原型之后是不等的:"+(SubType.prototype===SubPro));
//这里可以看出原型已经改变了
SubType.prototype.getSubValue = function(){
return this.subproperty;
}
var instance = new SubType();
//****************************
//下面开始证明图
//****************************
console.log("window对象下面添加了一个函数SuperType:"+(window.hasOwnProperty('SuperType')));
console.log("window对象下面添加了一个函数SubType:"+(window.hasOwnProperty('SubType')));
//下面全部为true
console.log("1:"+(SuperType.prototype===SuperType.prototype));
console.log("2:"+(SuperType===SuperType.prototype.constructor));
//不能直接找到new SuperType,我们用5来获取
console.log("3:"+(SubType.prototype.__proto__===SuperType.prototype));
console.log("4:"+(SubType.prototype.constructor===SuperType));
console.log("5:上面3,4已经顺带一起证明了,而且直接看代码就可以看出来了");
//我们用SubPro暂存了原来的原型
console.log("6:"+(SubPro.constructor===SubType));
//还是因为取不到new SuperType,我们用SubType.prototype来获取
console.log("7:"+(instance.__proto__===SubType.prototype));
console.log("8:"+(instance.constructor===SuperType));
//****************************
//下面开始证明各自的属性位置
//****************************
console.log("instance有私有的subproperty属性:"+(instance.hasOwnProperty('subproperty')));
console.log("new SuperType有私有的property属性:"+(SubType.prototype.hasOwnProperty('property')));
console.log("SuperType.prototype拥有私有的getSuperValue属性:"+(SuperType.prototype.hasOwnProperty('getSuperValue')));
console.log("SubType.prototype(换过的原型)拥有私有的getSubValue属性:"+(SubType.prototype.hasOwnProperty('getSubValue')));
console.log("SubPro(原来的原型)拥有私有的getSubValue属性:"+(SubPro.hasOwnProperty('getSubValue')));//false原来的原型没有getSubValue函数,因为是换了原型再添加的函数,所以函数存在实例里面
</script>
</body>
</html>


下面梳理一下原型链继承:(点击看大图)

这里通过一个SuperType实例替换SubType的原来的原型,这里的SuperType实例本身就拥有SuperType构造函数以及SuperType.prototype自带的一些属性,那么当取代SubType.prototype(原来的)之后,自然而然的instance实例的属性找不到的要到SubType的原型里面去找,而原来的原型已经被替换了,那么新原型里面有的属性就成了instance可以找到的属性了。ps:这里文字真心不好表达,反正就是往构造函数和构造函数原型找的意思。

这里当然也发生了略微有点奇怪的两点:

  1. __proto__属性指向新原型(本来是指向旧的SubType.prototype也就是SubPro的),这里勉强可以理解,换了原型嘛!
  2. constructor指向了SuperType构造函数(没有改变原型的话是指向SubType构造函数的),无法理解,代码是var instance = new SubType();怎么顺便把constructor属性也换了?

但是问题存在我们依旧可以很好理解JS的原型链继承:通过新的实例继承父构造函数与其原型的属性,然后通过替换子构造函数原型达到继承的目的。


非常建议看过《JavaScript高级程序设计(第三版)》的童鞋看完上面之后回去把书里面原型链这一节看一下,对比一下。如果有问题请留言。万分感谢!如果觉得我写的有用的话请点个赞,这是对我最大的鼓励!么么哒^_^

原文地址:请点击这里

 

8条规则图解JavaScript原型链继承原理的更多相关文章

  1. javascript原型链继承

    一.关于javascript原型的基本概念: prototype属性:每个函数都一个prototype属性,这个属性指向函数的原型对象.原型对象主要用于共享实例中所包含的的属性和方法. constru ...

  2. JavaScript学习总结(十七)——Javascript原型链的原理

    一.JavaScript原型链 ECMAScript中描述了原型链的概念,并将原型链作为实现继承的主要方法.其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法.在JavaScript中, ...

  3. 图解Javascript原型链

    本文尝试阐述Js中原型(prototype).原型链(prototype chain)等概念及其作用机制.上一篇文章(图解Javascript上下文与作用域)介绍了Js中变量作用域的相关概念,实际上关 ...

  4. JavaScript原型链及其污染

    JavaScript原型链及其污染 一.什么是原型链? 1.JavaScript中,我们如果要define一个类,需要以define"构造函数"的方式来define: functi ...

  5. javascript中继承(一)-----原型链继承的个人理解

    [寒暄]好久没有更新博客了,说来话长,因为我下定决心要从一个后台程序员转为Front End,其间走过了一段漫长而艰辛的时光,今天跟大家分享下自己对javascript中原型链继承的理解. 总的说来, ...

  6. JavaScript之原型链与原型链继承

    原型链 定义:每个实例对象(object)都有一个私有属性(称之为 __proto__ )指向它的构造函数的原型对象(prototype).该原型对象也有一个自己的原型对象(__proto__),层层 ...

  7. 一步步学习javascript基础篇(5):面向对象设计之对象继承(原型链继承)

    上一篇介绍了对象创建的几种基本方式,今天我们看分析下对象的继承. 一.原型链继承 1.通过设置prototype指向“父类”的实例来实现继承. function Obj1() { this.name1 ...

  8. Javascript 组合继承 原型链继承 寄生继承

    Javascript继承通常有三种方式. 第一种:组合式继承: function SuperType(name) { this.name = name; this.colors = ["re ...

  9. 三张图搞懂JavaScript的原型对象与原型链 / js继承,各种继承的优缺点(原型链继承,组合继承,寄生组合继承)

    摘自:https://www.cnblogs.com/shuiyi/p/5305435.html 对于新人来说,JavaScript的原型是一个很让人头疼的事情,一来prototype容易与__pro ...

随机推荐

  1. android开发笔记(一)Android studio 输入法

    以前都是用的时候查资料做些增添即可,现在下决心系统学习下. 首先发现developer.Android.com在开发工具上开始推出了 Android Studio了,不过他自己没有sdk manage ...

  2. C++的全部目标就是最优化资源的利用,以人付出更多为代价。Python刚好是另一个极端(Bjarne就说,一个人至少应该掌握两种计算机语言)

    说 C++ 反人类,是如果把 C++ 看作人(程序员)和资源(电子系统)的桥梁,他的全部目标就是最优化资源的利用,以人付出更多为代价.Python刚好是另一个极端.做好两个一起学.Bjarne就说,一 ...

  3. 关闭linux的防火墙

    有两道防火墙 第一道 iptables -L iptables -F systemctl disable firewalld 第二道 [root@python3 ~]# getenforce Enfo ...

  4. visual studio 2015开发nodejs教程1搭建环境

    http://sailsdoc.swift.ren/ 这里有 sails中文文档 1 安装nodejsv6.10.3 下载地址  https://nodejs.org/dist/v6.10.3/nod ...

  5. (C++) Assertion failed: !"Bad error code", file VMem.c, line 715

    (C++) Assertion failed: !"Bad error code", file VMem.c, line 715 Misc error. myInterface F ...

  6. Tornado 自定义Form,session实现方法

    一. 自定义Tornado 验证模块 我们知道,平时在登陆某个网站或软件时,网站对于你输入的内容是有要求的,并且会对你输入的错误内容有提示,对于Django这种大而全的web框架,是提供了form表单 ...

  7. 【Unity3D】使用MD5值,确保本地Sqlite数据库内容没有被篡改

    Sqlite的应用场景 在判断是否使用存储格式为Sqlite模式的标准,我们的标准是内容只读.也就是说,除非发布者修改Sqlite内容,玩家只有读取的权限. 换个角度说,Sqlite里面的数据都是游戏 ...

  8. linux meta 18.0.1 系统安装nodejs

    前置条件是:需要准备sudo apt-get 命令 第一步: 执行命令sudo apt-get install nodejs 即可安装, 之后可使用node -v 查看版本node 版本号 第二步: ...

  9. Eclipse 导入Maven 项目报错

    新建Maven项目时出错:org.apache.maven.archiver.MavenArchiver.getManifest   新建Maven项目时出错:org.apache.maven.arc ...

  10. Selenium(Webdriver)自动化测试常问到的问题解答(转自:潜龙0318)

    今天朋友问我了几个关于Selenium自动化测试的问题,我看了一下感觉还比较典型.结合我以往自动化测试的经验,给出了一些儿粗浅的答案,希望能帮大家,如果大家有什么好的看法,希望相互交流,相互学习! ( ...