JavaScript的原型链

news/2024/4/29 1:33:52/文章来源:https://blog.csdn.net/cheng521521/article/details/128440507

JavaScript的原型链

JavaScript的继承主要是通过原型链实现的,所以理解原型链是掌握JavaScript继承的关键一环。原型链的继承的基本思想是通过原型链继承多个引用类型的属性和方法。

理解原型链

关于原型链的定义与理解:

每个构造函数都有一个原型对象,原型有一个属性指向构造函数,而实例有一个内部指针指向原型。但是如果原型是另外一个类型的实例呢,那么就意味着这个原型本身有一个内部指针指向另外一个原型,相应地另外一个原型也有一个指针指向另一个构造函数。这样实例和原型之间构造了一条原型链。这就是原型链的基本思想构成。

阅读下面的代码,来深入理解原型链:

function SuperType () {this.property = true;
}SuperType.prototype.getSuperValue = function () {return this.property;
}function SubType() {this.subproperty = false;
}// 现在让之类继承父类SuperTypeSubType.prototype = new SuperType()SubType.prototype.getSubValue = function() {return this.subproperty;
};const instance = new SubType();console.log(instance.getSuperValue());

上面代码定义了两个类:父类SuperType和子类SubType,并且分别定义了一个属性和方法。其中SubType是通过创建SuperType的实例并将其赋值给自己的原型(SubType.prototype)实现了对SuperType的继承。这个赋值重写了SubType最初的原型,并将其替换为SuperType的实例。这就意味着SuperType实例可以访问的属性和方法也会存在于SubType.prototype

在这里插入图片描述

这个例子中实现继承的关键,是SubType没有使用默认原型,而是将其替换成了一个新的对象。这个新的对象恰好是SuperType的实例。这样一来,SubType的实例不仅能从SuperType的实例中继承属性和方法,而且还与SuperType的原型挂上了钩。于是instance(通过内部的[[Prototype]])指向SubType.prototype,而SubType.prototype(作为SuperType的实例又通过内部的[[Prototype]])指向SuperType.prototype。注意,getSuperValue()方法还在SuperType.prototype对象上,而property属性则在SubType.prototype上。这是因为getSuperValue()是一个原型方法,而property是一个实例属性。SubType.prototype现在是SuperType的一个实例,因此property才会存储在它上面。还要注意,由于SubType.prototypeconstructor属性被重写为指向SuperType,所以instance.constructor也指向SuperType.

默认情况下,所有引用类型都继承自Object,这也是通过原型链实现的。任何函数的默认原型都是一个Object的实例,这意味着这个实例有一个内部指针指向Object.prototype。这也是为什么自定义类型能够继承包括toString()valueOf()在内的所有默认方法的原因。SubType继承SuperType,而SuperType继承Object。在调用instance.toString()时,实际上调用的是保存在Object.prototype上的方法。

我们知道,在读取实例上的属性时,首先会在实例上搜索这个属性。如果没找到,则会继承搜索实例的原型。在通过原型链实现继承之后,搜索就可以继承向上,搜索原型的原型。对前面的例子而言,调用instance.getSuperValue()经过了3步搜索:instanceSubType.prototypeSuperType.prototype,最后一步才找到这个方法。对属性和方法的搜索会一直持续到原型链的末端。这就是原型链的向上搜索功能。

原型链与继承

原型与实例的关系可以通过两种方式来确定:instanceofisPrototypeOf

instanceof操作符

使用instanceof操作符,如果一个实例的原型链中出现过相应的构造函数,则instanceof返回true。示例如下:

console.log(instance instanceof Object); // true
console.log(instance instanceof SuperType); // true
console.log(instance instanceof SubType); // true 

因为instanceObjectSuperTypeSubType,所以使用instanceof操作符返回true

isPrototypeOf方法

使用isPrototypeOf()方法。原型链中的每个原型都可以调用这个方法,如下例所示,只要原型链中包含这个原型,这个方法就返回true

console.log(Object.prototype.isPrototypeOf(instance)); // true
console.log(SuperType.prototype.isPrototypeOf(instance)); // true
console.log(SubType.prototype.isPrototypeOf(instance)); // true 

原型链继承所面临的问题

新增或重新方法的要点

子类可以增加新的方法或者覆盖父类的方法

// 覆盖父类的方法
SubType.prototype.getSuperValue = function() {return false;
};

需要注意的是,我们应该避免使用以对象字面量方式创建原型方法,在会破坏之前的原型链,因为这相当于重写
了原型链。

function SuperType () {this.property = true;
}SuperType.prototype.getSuperValue = function () {return this.property;
}function SubType() {this.subproperty = false;
}// 现在让之类继承父类SuperTypeSubType.prototype = new SuperType()SubType.prototype = {getSubValue() {return this.subproperty;},getOtherMethod() {return false;}
}

在这段代码中,子类的原型在被赋值为SuperType的实例后,又被一个对象字面量覆盖了。覆盖后的原型是一个Object的实例,而不再是SuperType的实例。因此之前的原型链就断了。SubTypeSuperType之间也没有关系了。

原型链继承的引用问题

原型链虽然是实现继承的强大工具,但它也有问题。主要问题出现在原型中包含引用值的时候。前面在谈到原型的问题时也提到过,原型中包含的引用值会在所有实例间共享,这也是为什么属性通常会在构造函数中定义而不会定义在原型上的原因。在使用原型实现继承时,原型实际上变成了另一个类型的实例。这意味着原先的实例属性摇身一变成为了原型属性。

function SuperType() {this.colors = ["red", "blue", "green"];
}
function SubType() {}
// 继承 SuperType
SubType.prototype = new SuperType();let instance1 = new SubType();instance1.colors.push("black");console.log(instance1.colors); // "red,blue,green,black"// 因为colors是因为类型,上一个实例instance1修改了属性,进而影响了第二个实例
let instance2 = new SubType();
console.log(instance2.colors); // "red,blue,green,black" 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_240152.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Sentinel流控

Sentinel 随着微服务的流行,服务和服务之间的稳定性变得越来越重要。 Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。 1.sentinel特性 Sentinel 具有以下特征: 丰富的应用场景: Sentinel 承接了…

【折腾服务器 3】群晖学习版中安装 Active Backup for Business 及相关配置 =)

Catch UP 书接上回,在 ESXi 中安装了群晖系统,这个系统主要是用来给 Windows 物理机做备份的,因此在本片主要讲解如何配置 Active Backup for Business 软件。 Chapter 1 设置存储空间 上一篇博客中,安装群晖时分配了一个 32GB…

【高精度定位】关于GPS、RTK、PPK三种定位技术的探讨

高精度定位通常是指亚米级、厘米级以及毫米级的定位,从市场需求来看,定位的精度越高往往越好。“高精度、低成本”的定位方案无疑将是未来市场的趋势。 在物联网时代,大多数的应用或多或少都与位置服务相关联,尤其是对于移动物体而…

「 理财与风险控制|养老系列」你想象中的高端养老社区是什么样?

本文主要介绍为什么养老规划需要考虑养老社区的部分,当前市场上养老社区的各种现状,养老社区从各个角度分类,选择养老社区需要关注的要素以及保险保单能够提供的养老权益是怎样的 文章目录01 为什么要关注养老社区?02 为什么关注高…

【docker常用命令】

一、帮助启动类命令 (1)启动docker systemctl start docker(2)停止docker systemctl stop docker(3)重启docker systemctl restart docker(4)查看docker状态 systemctl status…

移动端测试必备技能: adb命令和抓包

移动端测试 是指对移动应用进行的测试,即实体的特性满足需求的程度,进行测试前需要搭建测试环境。 1 移动端自动化环境搭建 1.1 java安装 java JDK 安装jdk-8u181-windows-x64.exe 配置环境变量: JAVA_HOME:D:\developer to…

【c++】STL--vector

前言 想必大家已经对string有所了解了,string是专门用于字符串的。今天讲到的vector则是表示可变大小数组的序列容器。就像数组一样,vectoer也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组…

SpringBoot系列之自动装配原理详解

文章目录前言一、SpringBoot自动配置-Condition-11、观察spring自动创建bean过程2、创建自定义bean对象3、根据条件创建自定义bean二、 SpringBoot自动配置-Condition-2三、SpringBoot自动配置-切换内置web服务器1、查看继承关系图2、shiftdelete 排除Tomcat四、SpringBoot自动…

12.20工作学习记录 力扣 罗马文转数字

每日一题:罗马文转数字 定义两个指针 不断后移 每一次让前一个指针的值累加为sum 最后返回sum 力扣https://leetcode.cn/problems/roman-to-integer/ 最长公共前缀 主要是subString方法 力扣https://leetcode.cn/problems/longest-common-prefix/solutions/现在分词与形容…

圣诞的荒诞小故事并记录互联网协议-五层模型

今天敲代码敲着敲着灵光乍现,突然一个荒诞的故事💡映入脑海。 1.未来和过去: 人高度发达(以下称之为渡) 渡可以打开时空穿越过去(以下称之为旧迹),并且可以进随心所欲的来去自如&a…

基于yolov5s实践国际象棋目标检测模型开发

在我前面的一篇文章中讲解实现了基于改进的yolov5s-spd模型实现了五子棋目标对象检测模型系统的设计开发,这里紧接前文,突发奇想,是否可以借鉴同样的思路实现象棋的检测模型开发呢?理论上面肯定是可以的,但是实际效果如…

详细介绍关于自定义类型:结构体、枚举、联合【c语言】

文章目录结构体结构体的声名特殊的声明结构成员的类型结构的自引用结构体变量的定义和初始化结构体内存对齐修改默认对齐数结构体变量访问成员结构体传参结构体实现位段(位段的填充&可移植性)位段的内存分配位段的跨平台问题枚举枚举类型的定义枚举的…

微信小程序入门

目录 一,简介 二,小程序开发环境搭建 1.申请账号 2.安装开发工具 3.小程序工具使用 三,目录结构以及json配置 1.目录结果 2.json配置 3.JSON 语法 4.WXML 5.wxss 6.JS 逻辑交互 四,小程序宿主环境 1.程序与页面 2.组件…

String 字符串

String 基本介绍 String 应该是 Java 中最常用的一个对象&#xff0c;他不是八种基本数据类型的其中之一&#xff0c;但是随便翻了一下项目代码&#xff0c;用 String 定义的变量超过百分之八十。 public final class Stringimplements java.io.Serializable, Comparable<…

自己整理的vue实现生成分享海报(含二维码),看着网上的没实现

大家好&#xff0c;我是雄雄。 前言 相信大家在许多的场景下&#xff0c;看到过这样的案例。 当我们在某购物app上看好一件商品&#xff0c;想分享给别人时&#xff0c;app会给我们生成一张海报&#xff0c;我们将其保存在手机里面转发给其他人达到分享。当我们逛CSDN的时候&…

12.25日周报

周报 代码行数&#xff1a; 周一 704 周二 481 周三 571 周四 589 周五 595 周六 520 周日 537 遇到的问题&#xff1a; 没用过的方法AtomicInteger Insert Proto currentTimeMillis RequestParam BufferedReader UriComponents RestTemplate OSS 不清楚在…

Windows和Mac系统实现本地部署WebPageTest工具

在项目开发或者测试的过程中&#xff0c;由于没有上线&#xff0c;我们在公网上无法访问我们的网站&#xff0c;但同时我们又需要查看浏览器性能&#xff0c;这样我们就需要在本地部署WebPageTest工具以协助进行性能测试 具体实现步骤&#xff1a; Windows系统&#xff1a; …

【高级篇04】MySQL逻辑架构

文章目录第四章&#xff1a;逻辑架构逻辑架构SQL执行流程数据库缓冲池第四章&#xff1a;逻辑架构 逻辑架构 第一层&#xff1a;连接层。客户端访问MySQL服务器&#xff0c;首先建立TCP连接&#xff0c;经过三次握手建立连接成功后&#xff0c;MySQL服务器对TCP传输过来的账号…

PHP开发工具PhpStorm v2022.3——完全支持PHP 8.2

PhpStorm是一个轻量级且便捷的PHP IDE&#xff0c;其旨在提高用户效率&#xff0c;可深刻理解用户的编码&#xff0c;提供智能代码补全&#xff0c;快速导航以及即时错误检查。可随时帮助用户对其编码进行调整&#xff0c;运行单元测试或者提供可视化debug功能。 PhpStorm v20…

excel数据处理技巧:组合函数统计产品批号

这是一个看似普通的编号问题&#xff0c;可竟然动用了TEXT和SUMPRODUCT两个重量级的函数共同出手才得以解决。以往遇到的编号问题&#xff0c;大多数都是COUNTIF的拿手好戏&#xff0c;但是今天这个问题COUNTIF完全插不上手&#xff0c;来看看模拟的数据吧。 如图所示&#xff…