1前言

继承是JavaScript中的重要概念,可以说要学好JavaScript,必须搞清楚JavaScript中的继承。我最开始是通过看视频听培训班的老师讲解的JavaScript中的继承,当时看的时候好像是理解了,可是没过多久就忘了,说明当时学的时候只是死记硬背,而没有深入理解,所以容易遗忘。因此,我认为,一个知识点,如果是真的弄明白了其中的原理,是不需要强行记忆的,真正理解之后会有一种融会贯通的感觉,自然而然就存在于脑海中了。废话不多说了,今天我是在看了《JavaScript高级程序设计》之后,才感觉真正理解了JavaScript中的继承,故而写下这篇博客记录一下。

2原型链

  原型链是实现继承的主要方法。那么何为原型链呢?要回答这个问题,首先要从构造函数、原型对象和实例对象三者的关系讲起。实例对象是由构造函数创建的,构造函数中有一个prototype属性,可以看成一个指针,它指向原型对象,实例对象中有一个_proto_属性,它的指针也指向原型对象,而原型对象中有一个constructor属性,它指向的是构造函数,这样就形成了如下图所示的一个关系图(图是直接用的别人的,这个图没有把constructor画出来)。

  接下来,重点来了,如果我们让原型对象等于另一个类型的实例,那么此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么如此层层递进,就构成了实例与原型的链条。这就是所谓原型链的基本概念。

3继承

3.1通过原型链继承

  首先,如何通过原型链继承?请看以下代码:

function SuperType() {
this.property = true;
}
SuperType.prototype.getSuperValue = function () {
return this.property;
}
function SubType() {
this.subproperty = false;
}
SubType.prototype = new SuperType();//这里就是让子类型的原型对象等于超类型的实例,从而继承了超类型SuperType
SubType.prototype.getSubValue = function () {
return this.subproperty;
}
var instance = new Subtype();
alert(instance.getSuperValue());//true

  实现继承的本质是重写原型对象,代之以一个新类型的实例。

  那么,通过原型链实现继承有什么缺点?第一个问题,来自包含引用类型值的原型。包含引用类型值的原型属性会被所有实例共享,一旦在一个实例中修改了属性值,其他任何实例中的该属性值也随之改变了,也就是实例对象就无法拥有自身的私有属性了。第二个问题,在创建子类型的实例时,不能向超类型的构造函数中传递参数。

3.2借用构造函数继承

  为了解决原型链继承中存在的一些问题,借用构造函数实现继承的方法就产生了,请看以下代码:

function SuperType(name) {
this.name = name;
}
function SubType() {
SuperType.call(this,"smalldy");
this.age = 24;
}
var instance = new SuperType();
alert(instance.name);//"smalldy"
alert(instance.age);//24

  借用构造函数实现继承也有缺点,也就是在超类型的原型中定义的方法,对子类型而言是 不可见的,结果所有方法都在构造函数中定义,无法实现函数复用。

3.3组合继承

  组合继承的思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承,请看以下代码:

function SuperType(name) {
this.name = name;
this.colors = ["red","blue","green"];
}
SuperType.prototype.sayName = function () {
alert(this.name);
};
function SubType(name,age) {
SuperType.call(this,name);
this.age = age;
}
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function () {
alert(this.age);
};
var instance1 = new SubType("smalldy",24);
instance1.colors.push("black");
alert(instance1.colors);
instance1.sayName();
instance1.sayAge();
var instance2 = new SubType("youcaihua",25);
alert(instance2.colors);
instance2.sayName();
instance2.sayAge();

  组合继承避免了原型链和借用构造函数的缺陷,融合了它们的优点。

3.4原型式继承

  思路:基于已有的对象创建新对象。

function object(o) {
function F() {
}
F.prototype = o;
return new F();
}

  将一个对象作为另一个对象的基础,把它传递给object()函数,然后再根据具体需求对得到的对象加以修改即可。

3.5寄生式继承

  思路:创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真的是它做了所有工作一样返回对象。

function createAnother(original) {
var clone = object(original);
clone.sayHi = function () {
alert("hi")
};
return clone;
}

3.6寄生组合式继承

  组合继承最大的问题就是无论什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数内部。

  所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。

function inheritPrototype(subType,superType) {
var prototype = object(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}

  函数接收两个参数:子类型构造函数和超类型构造函数。在函数内部,第一步是创建超类型原型的一个副本。第二步是为创建的副本添加constructor属性,从而弥补因重写原型而失去的默认的constructor属性。最后一步,将新创建的对象赋值给子类型的原型。

  寄生组合式继承是引用类型最理想的继承范式。

深入理解JavaScript中的继承的更多相关文章

  1. 深入理解JavaScript中的继承:原型链篇

    一.何为原型链 原型是一个对象,当我调用一个对象的方法时,如果该方法没有在对象里面,就会从对象的原型去寻找.JavaScript就是通过层层的原型,形成原型链. 二.谁拥有原型 任何对象都可以有原型, ...

  2. 理解JavaScript中的原型继承(2)

    两年前在我学习JavaScript的时候我就写过两篇关于原型继承的博客: 理解JavaScript中原型继承 JavaScript中的原型继承 这两篇博客讲的都是原型的使用,其中一篇还有我学习时的错误 ...

  3. JavaScript中的继承(原型链)

    一.原型链 ECMAScript中将原型链作为实现继承的主要方法,基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法. 实例1: function SupType() { this.pro ...

  4. 深入理解JavaScript中创建对象模式的演变(原型)

    深入理解JavaScript中创建对象模式的演变(原型) 创建对象的模式多种多样,但是各种模式又有怎样的利弊呢?有没有一种最为完美的模式呢?下面我将就以下几个方面来分析创建对象的几种模式: Objec ...

  5. 理解 JavaScript 中的 this

    前言 理解this是我们要深入理解 JavaScript 中必不可少的一个步骤,同时只有理解了 this,你才能更加清晰地写出与自己预期一致的 JavaScript 代码. 本文是这系列的第三篇,往期 ...

  6. 彻底搞懂JavaScript中的继承

    你应该知道,JavaScript是一门基于原型链的语言,而我们今天的主题 -- "继承"就和"原型链"这一概念息息相关.甚至可以说,所谓的"原型链&q ...

  7. 深入理解 JavaScript 中的 class

    在 ES6 规范中,引入了 class 的概念.使得 JS 开发者终于告别了,直接使用原型对象模仿面向对象中的类和类继承时代. 但是JS 中并没有一个真正的 class 原始类型, class 仅仅只 ...

  8. JavaScript学习13 JavaScript中的继承

    JavaScript学习13 JavaScript中的继承 继承第一种方式:对象冒充 <script type="text/javascript"> //继承第一种方式 ...

  9. 深入理解JavaScript中的属性和特性

    深入理解JavaScript中的属性和特性 JavaScript中属性和特性是完全不同的两个概念,这里我将根据自己所学,来深入理解JavaScript中的属性和特性. 主要内容如下: 理解JavaSc ...

随机推荐

  1. HLS后端示例

    HLS后端示例 TVM支持带有SDAccel的Xilinx FPGA板.这是有关如何将TVM部署到AWS F1 FPGA实例的文档. 此功能仍处于试验阶段.暂时无法使用SDAccel部署端到端神经网络 ...

  2. 自主数据类型:在TVM中启用自定义数据类型探索

    自主数据类型:在TVM中启用自定义数据类型探索 介绍 在设计加速器时,一个重要的决定是如何在硬件中近似地表示实数.这个问题有一个长期的行业标准解决方案:IEEE 754浮点标准.1.然而,当试图通过构 ...

  3. Excel创建手机号1000个

    一.输入手机号15900000001,并且选择 二.选中这一列 三.按住Ctrl,鼠标选中创建手机号,取消选中的状态 四.开始-填充 五.选择序列 六.选择列-自动填充-点击确定 七.查看结果,生成成 ...

  4. 重新整理 .net core 实践篇—————日志系统之作用域[十七]

    前言 前面介绍了服务与日志之间的配置,那么我们服务会遇到下面的场景会被遇到一些打log的问题. 前面我提及到我们的log,其实是在一个队列里面,而我们的请求是在并发的,多个用户同时发送请求这个时候我们 ...

  5. Java基础知识之this关键字知识讲解

    this关键字这里对java中this关键字的基础知识进行讲解,希望对热爱java的小伙伴有帮助!! /* this关键字代表了所属函数的调用者对象. this关键字的作用: 1. 如果存在同名成员变 ...

  6. 在VScode 中使用RT-Thread Studio初体验

    前言 工欲善其事,必先利其器,VScode是什么东东,想必大家都非常熟悉了,丰富的插件,有好的开发界面,是很多程序开发者的不二之选,RT-Thread竟然也开发了Vscode插件,真的是非常的nice ...

  7. 实现SLIC算法生成像素画

    前言 像素风最早出现在8bit的电子游戏中,受制于电脑内存大小以及显示色彩单一, 只能使用少量像素来呈现内容,却成就了不少经典的像素游戏.随着内存容量与屏幕分辨率的提升,内存与显示媒介的限制不再是问题 ...

  8. [源码解析] 深度学习分布式训练框架 horovod (7) --- DistributedOptimizer

    [源码解析] 深度学习分布式训练框架 horovod (7) --- DistributedOptimizer 目录 [源码解析] 深度学习分布式训练框架 horovod (7) --- Distri ...

  9. git 认证问题之一的解决 : http ssh 互换

    场景 使用git 我们经常会遇到 认证失败的情况,有时候确实是搞错了用户名或者密码,还有的时候及时用户名密码用对了也还是认证失败. 此时, 就有可能是下面这个情况. 没有配置 ssh 秘钥, 而用了 ...

  10. AI框架中图层IR的分析

    摘要:本文重点分析一下AI框架对IR有什么特殊的需求.业界有什么样的方案以及MindSpore的一些思考. 本文分享自华为云社区<MindSpore技术专栏 | AI框架中图层IR的分析> ...