js中的原型链

编写思路:

  1. 简单介绍构造函数
  2. 介绍原型对象
  3. 原型对象、实例的关系,从而引出原型链的基本概念

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

1. 什么是构造函数

构造函数本身跟普通函数一样,也不存在定义构造函数的特殊语法。唯一区别在于调用的方式不同,任何函数只要通过new 操作符来调用,都可以叫做构造函数。默认情况下构造函数的首字母大写,不大写也没有问题,主要是为了与普通函数区分。

2. 原型对象

创建一个新函数都会有一个prototype(原型)属性,这个属性指向函数的原型对象。

prototype原型属性

在默认情况下,所有原型对象都会自动获得一个constructor(构造函数)属性,这个属性是一个指向prototype属性所在函数的指针(也就是构造函数)。创建一个自定义构造函数之后,其原型对象默认只会取得constructor属性,其他方法,则会从Object继承而来的。

constructor属性

当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性),指向构造函数的原型对象。这个指针(内部属性)叫做[[Prototype]],可以通过_proto_进行或者。用它来连接实例与构造函数的原型对象。

proto

如何读取属性值:当对象某个对象属性时,首先先从对象实例本身开始读取,如果存在就返回,不存在就开始向原型对象查找属性。

3. 构造函数、原型、实例之间的关系

每个构造函数都有一个prototype(原型)属性,指向原型对象,而原型对象中有一个指向构造函数的指针,实例有一个指向原型对象的指针。

显示原型:每个构造函数都有一个prototype(原型)属性,指向原型对象。

隐式原型:实例有一个指向原型对象的指针(_proto_)。

假设: 让原型对象等于另一个类型的实例,会怎么样?

答:此时的原型对象将包含一个指向另一个原型(B)的指针,相应的,另一个原型(B)中也包含着一个指向另一个构造函数(B)的指针,假如另一个原型(B)又是另一个类型的实例,那么上述关系依然成立,如此层层递进,就构造了实例与原型的链条,也就是所谓原型链的基本概念。

function Person () {this.name = '张三';
}
Person.prototype.getName = function() {return this.name;
}function Student() {this.age = 18;
}// 将Person实例赋值给Student的原型对象
Student.prototype = new Person();Student.prototype.getAge = function(){return this.age;
}
var student1 = new Student();
console.log(student1.getName); // '张三'

上面代码解释:

  • 创建了两个构造函数,分别是Person、Student。
  • 在Person中定义了name属性,在其原型对象中添了一个getName方法。
  • 在Student定义了age属性,并将Person实例赋值给Student的原型对象。
  • 在修改Student原型对象后又在其原型对象后添加getAge方法。
  • 创建Student实例student1。
  • 打印实例student1的getName方法。

图片展示上面代码中各个构造函数、原型、实例的关系

原型链例子

解释上面代码中的关系

  1. 根据前面知识知道,构造函数中有一个prototype属性指向原型对象,原型对象中有一个constructor属性指回原型对象所在的构造函数,实例中有一个指针指向其构造函数的原型对象。根据这句话图中一部分的箭头(标号为1)指向很清楚的能解释。
  2. 代码中将Person的实例对象赋值给了Student的原型对象,而每个实例都有一个指向其构造函数的原型,所以此时Student的原型中有一个指向Person原型对象的指针。 可以解释图中标号为2的箭头。
  3. 在这里再提一下,为什么Student的原型对象中会有getAge方法,是因为定义getAge方法在修改Student原型对象之后。
  4. 最后一句代码为什么会能打印出来?因为当查找一个属性时,会先在自身查找,如果不存在则会再原型中查找,虽然在Student的原型对象没有查找到,但是其中又有一个指针指向另一个原型对象,可以再次查找,所以会找到。
  5. 最后一层层的查找,就变成了原型链。其实原型链是实例与原型之间的关系,跟构造函数没有任何关系。

记住所有函数的默认原型都是Object实例,因此默认原型中都有一个指针,指向Object.prototype,这就是所有自定义类型都会继承toString()等方法的根本原因。

这里的代码Student继承了Person,而Person继承了Object,如果student1调用toString方法,是调用的Object.prototype中的那个方法。

总结:

  • 访问对象的一个属性,先在自身查找,如果没有,会访问对象的__proto__,沿着原型链查找,一直找到Object.prototype.__proto__
  • 每个函数都有prototype属性,会指向函数的原型对象。
  • 所有函数的原型对象的__proto__,会指向Object.prototype
  • 原型链的尽头是Object.prototype.__proto__,为null。

4. 检测原型与实例的关系

只要原型链中出现过的原型都是。

第一种使用instanceof操作符

student1 instanceof Object; // true
student1 instanceof Student; // true
student1 instanceof Person; // true

第二种isPrototypeOf()

Object.prototype.isPrototypeOf(student1); // true

5. 其他注意点

  1. 给原型添加方法一定要在替换原型语句之后,子类型会覆盖超类型中的某个属性或方法。比如说定义一个原型链中存在的属性和方法,在访问时只要访问到,就会立马返回值。
  2. 不能使用字面量给原型对象添加方法,否则会使原型对象与之前的构造函数断了联系。

6. 问题

  1. 通过原型继承时,原型实际上会变成另一个类型的实例。
  2. 在创建子类型的实例时,不能向超类型的构造函数传递参数。

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

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

相关文章

图神经网络 GNN

之前经常看到图神经网络的内容,但是一直都觉得很难,就没有继续了解,现在抽空学习了一下,简单了解GNN是个什么东西,还没有进行代码实践,随着后续的学习,会继续更新代码的内容,这里先记…

Linux动态链接库.so文件

一、动态库和静态库的区别 库是一个二进制文件,包含的代码可以被程序调用,如标准库、线程库。Windows 和 Linux下的库文件格式不兼容。 Windows环境:静态库是 .lib 文件,共享库是 .dll 文件 Linux环境:静态库是 .a 文…

数据结构与算法(八):排序算法

参考引用 Hello 算法 Github:hello-algo 1. 选择排序 选择排序的工作原理非常直接:开启一个循环,每轮从未排序区间选择最小的元素,将其放到已排序区间的末尾,设数组的长度为 n 初始状态下,所有元素未排序&…

HTTP协议的请求协议和响应协议的组成,HTTP常见的状态信息

HTTP协议 什么是协议 协议实际上是某些人或组织提前制定好的一套规范,大家只要都按照这个规范来就可以做到沟通无障碍 HTTP协议是W3C(万维网联盟组织)制定的一种超文本传输通信协议(发送消息的模板和数据的格式),除了传送字符串,还有声音、视频、图片等流媒体等超文本信息 …

伦敦银最新走势不利怎么办

跟其他的投资品种一样,伦敦银的价格走势在不停的变化,而且由于本身产品具有较高的资金杠杆,所以万一行情走势变得不利,在很短的时间之内就会对投资者的账户造成严重损失,所以投资者应该对此作好充分的准备。 伦敦银的最…

LabVIEW利用以太网开发智能液位检测仪

LabVIEW利用以太网开发智能液位检测仪 目前,工业以太网接口在国内外的发展已经达到了相当深入的程度,特别是在自动化控制和工业控制领域有着非常广泛的应用。在工业生产过程中,钢厂的连铸机是前后的连接环节,其中钢水从大钢包进入…

Spring Boot如何配置CORS支持

Spring Boot如何配置CORS支持 CORS(跨源资源共享)是一种Web浏览器的安全性功能,用于控制网页上的脚本文件从不同的源加载其他网页资源。在开发现代Web应用程序时,通常需要跨域请求不同的资源,如API服务或其他Web应用程…

一个tomcat下如何部署多个项目?

1、不修改端口,部署多个项目 清楚tomcat目录结构的应该都知道,项目包是放在webapps目录下的,那能否在同一个tomcat的webapps目录下运行多个不同项目呢? 答案是可以的。 1、将多个项目包放入webapps文件夹下 2、修改conf下的serv…

reactjs开发环境搭建

Reactjs是一个前端web页面应用开发框架工具集,其支持前端构建页面以及后端构建页面两种常用的开发场景,其中,支持reactjs的开发框架包括next.js、remix、gatsby以及其他,本文主要描述next.js开发环境的搭建,next.js是一…

Verilog HDL阻塞赋值和非阻塞赋值笔记

1. module test( input wire clk, input wire b, output reg a, output reg c ); always(posedge clk) begin ab; ca; end endmodule 上面的代码在vivado中综合后的电路为: 2. module test( input wire clk, input wire b, outp…

springcloud之项目实战环境准备

写在前面 为了更好的学习springcloud,我们来一起开发一个实战项目,加深理解。 1:项目介绍 在开始项目实战之前先来做一个整体的项目介绍,从而能够让对项目的整体架构和模板有一个比较清晰的认知。 大家都知道双11,…

JS进阶-原型

原型 原型就是一个对象,也称为原型对象 构造函数通过原型分配的函数是所有对象所共享的 JavaScript规定,每一个构造函数都有一个prototype属性,指向另一个对象,所以我们也称为原型对象 这个对象可以挂载函数,对象实…

64.最小路径和

法:动态规划 第一行的元素,只有通过左侧右移才能到达;第一列的元素,只有通过上方的下移才能到达。其他位置元素:比较从上方元素向下移动的路径和和左侧元素向右移动的路径和的较小值dp[i][j]:到达(i,j)位置…

中国移动咪咕、阿里云、华为“秀肌肉”,这届亚运会的“高光”不止比赛

文 | 智能相对论 作者 | 青月 竞技体育的发展,其实也可以看作是一部“技术进化史”。 在1924年的巴黎,广播首次进入奥运会,人们第一次可以通过报纸以外的方式了解奥运会。 1928年,在荷兰申办的阿姆斯特丹奥运会,高…

【jvm--方法区】

文章目录 1. 栈、堆、方法区的交互关系2. 方法区的内部结构3. 运行时常量池4. 方法区的演进细节5. 方法区的垃圾回收 1. 栈、堆、方法区的交互关系 方法区的基本理解: 方法区(Method Area)与 Java 堆一样,是各个线程共享的内存区…

【力扣】单调栈:901. 股票价格跨度

【力扣】单调栈:901. 股票价格跨度 文章目录 【力扣】单调栈:901. 股票价格跨度1. 题目介绍2. 思路3. 解题代码参考 1. 题目介绍 设计一个算法收集某些股票的每日报价,并返回该股票当日价格的 跨度 。 当日股票价格的 跨度 被定义为股票价格…

75.颜色分类

原地排序&#xff1a;空间复杂度为1 class Solution { public:void sortColors(vector<int>& nums) {if(0){//法一&#xff1a;单指针两个遍历int nnums.size();int ptr0;for(int i0;i<n;i){if(nums[i]0){swap(nums[i],nums[ptr]);ptr;}}for(int iptr;i<n;i){…

【Proteus仿真】【STM32单片机】汽车倒车报警系统设计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真STM32单片机控制器&#xff0c;使用LCD1602液晶、按键、继电器电机模块、DS18B20温度传感器、蜂鸣器LED、HCSR04超声波等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD1602显…

2021年03月 Python(二级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python编程&#xff08;1~6级&#xff09;全部真题・点这里 一、单选题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 第1题 对于字典infor {“name”:“tom”, “age”:13, “sex”:“male”}&#xff0c;删除"age":13键值对的操作正确的…

数据压缩与管理:掌握Linux VDO和LVM的力量

1.逻辑卷(LVM&#xff0c;Logical Volume Management) 动态的为服务器磁盘添加空间&#xff0c;而不会影响原磁盘的数据&#xff0c;也不需要对原始磁盘重新分区。 1.1 LVM介绍 以下是LVM的示意图&#xff1a; 我们拿到一块硬盘后首先对齐进行划分分区&#xff0c;也就得到…