博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JS面向对象的程序设计之继承的实现 - 原型链
阅读量:6005 次
发布时间:2019-06-20

本文共 2704 字,大约阅读时间需要 9 分钟。

JS面向对象的程序设计之继承的实现 - 原型链


前言:最近在细读Javascript高级程序设计,对于我而言,中文版,书中很多地方翻译的差强人意,所以用自己所理解的,尝试解读下。如有纰漏或错误,会非常感谢您的指出。文中绝大部分内容引用自《JavaScript高级程序设计第三版》。


继承是OO(Object Oriented, 面向对象)语言中的一个最为人津津乐道的概念。

许多OO语言都支持两种继承方式:接口继承和实现继承。

接口继承只继承签名,而实现继承则继承实际的方法。

如前所述, 由于函数没有签名,在ECMAScript中无法实现接口继承。

前面暂时看不懂没关系,可以学学一些Java基础知识,这样回过来看,就明白说啥了!!

记住这句就行,ECMAScript只支持实现继承,而且其实现继承主要是依靠原型链来实现的。

原型链

ECMAScript中描述了原型链的概念,并将原型链作为实现继承的主要方法。

其基本思想是利用原型,让一个引用类型继承另一个引用类型的属性和方法。

简单回顾一下构造函数、原型和实例对象之间的关系:

  • 每个构造函数都有一个原型对象。
  • 原型对象都包含一个指向构造函数的指针。
  • 实例对象都包含一个指向原型对象的内部指针。
//伪代码//构造函数function Person(){}//构造函数的原型对象中constructor指向构造函数自身Person.prototype.constructor => 指向 function Person(){}var person1 = new Person();//实例对象指向原型对象的内部指针。person1.__proto__ => 指向 Person.prototype

这部分,文字描述有些晦涩!看不懂的话,先看代码例子。

假如,我们让原型对象等于另一个类型的实例对象, 结果会怎么样呢?

显然,此时原型对象将包含一个指向另一个原型的指针。

相应地, 另一个原型中也包含着一个指向另一个构造函数原型的指针。

假如,另一个原型又是另一个类型的实例对象,还是包含一个指针指向另外一个构造函数的原型,所以上述关系依然成立。

如此层层递进,就构成了实例与原型的链条。

这就是所谓原型链的基本概念。

你可以想象成 “不断认祖归宗”的过程,认祖归宗的路径连接起来,就形成了一个“血缘链”。

实现原型链的基本模式

//实现原型链的示例代码//SuperType 父类型function SuperType(){    this.property = true;}SuperType.prototype.getSuperProperty = function() {    console.log(this.property);    return this.property;}//SubType 子类型function SubType() {    this.subproperty = false;}//子类型 继承 父类型SubType.prototype = new SuperType();//实际上子类型的原型是这样的。/*SubType.prototype = {    property: true,    __proto__:  {        constructor : SuperType,        getSuperProperty:function() {            console.log(this.property);            return this.property;        }    }}*/SubType.prototype.getSubProperty = function(){    console.log(this.subproperty);    return this.subproperty;}//那么现在子类型的原型对象是这样的/*SubType.prototype = {    property: true,    getSubProperty: function()  {    console.log(this.subproperty);    return this.subproperty;    },    __proto__:  {        constructor : SuperType,        getSuperProperty:function() {            console.log(this.property);            return this.property;        }    }}*/var subInstanceObject = new SubType();console.log(subInstanceObject.getSuperProperty()); // true

以上代码定义了两个类型(构造函数):

SuperType(父类型)和 SubType(子类型)。

每个类型分别有一个属性和方法。

它们主要的区别是SubType继承了SuperType(子类继承父类),而继承是通过创建SuperType的实例对象, 然后将实例对象赋予SubType.prototype(子类的原型)实现的。

实现的本质是重写原型,改写为另外一个类型的实例对象,

生成另外一个类型的实例对象的过程中,实例对象中的所有属性和方法,赋予给重写的原型,

重点,这个实例对象的内部有个属性__proto__指向,构造这个实例对象的构造函数原型,

从而实现继承,

属性__proto__,确实很像一条链子!

实现原型链,本质上扩展了原型搜索机制。

当读取或者访问一个实例属性时,首先会在实例中搜索该属性,如果没有找到该属性,则会沿着去搜索实例对象内部的__proto__指向的原型。

通过原型链实现继承,搜索过程,就像沿着一条链子不断向上搜寻。

就上面的示例代码来说,subInstanceObject.getSuperProperty()会经历三次查找!

查找过程

  1. 搜索实例对象自身, 没找到该方法,沿着__proto__找。
  2. 找到(构造)实例对象的构造函数的原型对象,还是没找到该方法,继续沿着原型对象的__proto__的指向寻找。
  3. 找到生成构造函数的原型对象的构造函数,搜索其原型对象,找到了。

在找不到属性或方法的情况下,搜索过程总是要一环一环地前行到原型链末端才会停下来。

转载地址:http://cnpmx.baihongyu.com/

你可能感兴趣的文章
kettle界面语言修改成中文后,重启报错
查看>>
nagios安装完后插件里没有check_mysql的解决方法
查看>>
梦想的脚步---C语言的学习与成长
查看>>
ubuntu 16.04 安装 Git SVN 图形化客户端 RabbitVCS
查看>>
谷歌Chrome开展实验,解决HTTPS混合内容错误
查看>>
全球.COM域名注册量统计:2月增超29万域名
查看>>
11月微博博客日均覆盖数TOP10:网易博客升至第七
查看>>
6月28日全球域名注册商(国际域名)保有量及市场份额
查看>>
9月第4周全球域名商(国际域名)新增注册量TOP15
查看>>
微软Silverlight 5开发书籍汇总
查看>>
Android热修复升级探索——代码修复冷启动方案
查看>>
我的友情链接
查看>>
如何提高阿里云上应用的可用性(一)
查看>>
如何更高效的管理原生微服务应用
查看>>
浮点数
查看>>
219. Contains Duplicate II - LeetCode
查看>>
MySQL数据库安装及配置相关
查看>>
小U盘大用处
查看>>
今天发现大量TIME_WAIT
查看>>
基于搜狗微信的爬虫知识总结
查看>>