深入解析 JavaScript 原型与原型链:从原理到应用

原型原型链是 JavaScript 中实现对象继承和属性查找的核心机制。为了更深入地理解它们,我们需要从底层原理、实现机制以及实际应用等多个角度进行分析。


1. 原型(Prototype)

1.1 什么是原型?

  • 每个 JavaScript 对象(除 null 外)都有一个内部属性 [[Prototype]],指向它的原型对象。
  • 原型对象也是一个普通对象,它包含可以被其他对象共享的属性和方法。
  • 通过 __proto__(非标准,但广泛支持)或 Object.getPrototypeOf() 可以访问对象的原型。

1.2 构造函数与原型

  • 每个函数(构造函数)都有一个 prototype 属性,指向一个对象,这个对象是该构造函数实例的原型。
  • 当使用 new 关键字创建实例时,实例的 [[Prototype]] 会指向构造函数的 prototype 对象。
function Person(name) {this.name = name;
}// 在构造函数的原型上添加方法
Person.prototype.sayHello = function() {console.log(`Hello, my name is ${this.name}`);
};const person1 = new Person('Alice');
person1.sayHello(); // 输出: Hello, my name is Alice
  • 在上面的例子中:
    • Person.prototypeperson1 的原型对象。
    • person1.__proto__ 指向 Person.prototype

2. 原型链(Prototype Chain)

2.1 什么是原型链?

  • 原型链是由对象的 [[Prototype]] 连接起来的链式结构。
  • 当访问对象的属性或方法时,如果对象本身没有该属性,JavaScript 会沿着原型链向上查找,直到找到该属性或到达原型链的顶端(null)。

2.2 原型链的顶端

  • 所有对象的原型链最终都会指向 Object.prototype,而 Object.prototype[[Prototype]]null
  • 如果在整个原型链中都找不到属性,则返回 undefined
console.log(person1.toString()); // 输出: [object Object]
  • 在上面的例子中:
    • person1 本身没有 toString 方法。
    • JavaScript 引擎会沿着原型链查找:
      1. person1 -> 没有 toString
      2. person1.__proto__(即 Person.prototype) -> 没有 toString
      3. Person.prototype.__proto__(即 Object.prototype) -> 找到 toString,调用它。

3. 原型链的深度分析

3.1 原型链的构建

  • 原型链是通过 [[Prototype]] 连接起来的。
  • 当我们创建一个对象时,它的 [[Prototype]] 会指向某个原型对象。
const obj = {};
console.log(obj.__proto__ === Object.prototype); // true
  • 如果我们手动修改 [[Prototype]],可以构建自定义的原型链。
const parent = { name: 'Parent' };
const child = Object.create(parent); // child.__proto__ 指向 parent
console.log(child.name); // 输出: Parent

3.2 原型链的查找机制

  • 当访问对象的属性时,JavaScript 引擎会按照以下步骤查找:
    1. 检查对象自身是否有该属性。
    2. 如果没有,沿着 [[Prototype]] 向上查找。
    3. 重复这个过程,直到找到属性或到达 null
const grandparent = { familyName: 'Smith' };
const parent = Object.create(grandparent);
const child = Object.create(parent);console.log(child.familyName); // 输出: Smith
  • 在上面的例子中:
    • child 自身没有 familyName
    • child.__proto__(即 parent)也没有 familyName
    • parent.__proto__(即 grandparent)有 familyName,返回 Smith

4. 原型链与继承

4.1 基于原型的继承

  • JavaScript 通过原型链实现继承。
  • 子类的原型对象指向父类的实例,从而继承父类的属性和方法。
function Person(name) {this.name = name;
}Person.prototype.sayHello = function() {console.log(`Hello, my name is ${this.name}`);
};function Student(name, grade) {Person.call(this, name); // 调用父类构造函数this.grade = grade;
}// 继承父类原型
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student; // 修复构造函数指向const student1 = new Student('Bob', 10);
student1.sayHello(); // 输出: Hello, my name is Bob
  • 在上面的例子中:
    • Student.prototype 的原型指向 Person.prototype
    • student1 可以访问 Person.prototype 上的方法。

4.2 原型链的局限性

  • 原型链继承是单向的,子类可以访问父类的属性和方法,但父类不能访问子类的属性和方法。
  • 如果原型链过长,属性查找的性能会受到影响。

5. 原型链的实际应用

5.1 共享方法

  • 将方法定义在原型上,可以避免每个实例都创建一份方法的副本,节省内存。
function Person(name) {this.name = name;
}Person.prototype.sayHello = function() {console.log(`Hello, my name is ${this.name}`);
};const person1 = new Person('Alice');
const person2 = new Person('Bob');// person1 和 person2 共享同一个 sayHello 方法
console.log(person1.sayHello === person2.sayHello); // true

5.2 扩展内置对象

  • 可以通过修改内置对象的原型来扩展其功能。
Array.prototype.last = function() {return this[this.length - 1];
};const arr = [1, 2, 3];
console.log(arr.last()); // 输出: 3

6. 总结

  • 原型:每个对象都有一个 [[Prototype]],指向它的原型对象。
  • 原型链:通过 [[Prototype]] 连接起来的链式结构,用于属性查找。
  • 继承:通过原型链实现对象之间的继承。
  • 性能:原型链过长会影响查找性能,需谨慎设计。

理解原型和原型链是掌握 JavaScript 面向对象编程的关键,也是深入理解 JavaScript 运行机制的基础。

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

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

相关文章

FPGA时序约束的几种方法

一,时钟约束 时钟约束是最基本的一个约束,因为FPGA工具是不知道你要跑多高的频率的,你必要要告诉工具你要跑的时钟频率。时钟约束也就是经常看到的Fmax,因为Fmax是针对“最差劲路径”,也就是说,如果该“最差劲路径”得到好成绩,那些不是最差劲的路径的成绩当然比…

Visual Studio Code打开远程服务器项目,打开服务器Android上百G源码,SSH免密连接方式

Visual Studio Code打开远程服务器项目 1,Visual Studio Code拓展中,安装远程插件 Remote Development 2,SSH免密连接,A电脑免密连接B,配置B电脑.ssh/authorized_keys A电脑的.ssh/id_rsa.pub中的公钥内容,…

AWS云编排详解-Cloud Formation

作者:私语茶馆 1.关键概念 名词 说明 软件: CloudFormation 描述AWS 资源、配置值和互连关系。借助集成设施即代码加快云部署 CloudFormation Designer 拖拽式图形化模板编辑界面。 Amazon Simple Notification Service (SNS) SNS可通过电子邮件跟踪堆栈的创建和删除进度,…

《PyQt5》——设计Python GUI(图形用户界面)实例

PyQt5 PyQt5的配置和基础使用可以参考这篇文章:《 PyQt5》—— 创建 Python GUI(图形用户界面) Python GUI(图形用户界面)实例 本实例是设计一个通过玉米和豆粕的价格来预测生猪的价格,并显示预测价格与实…

kali linux 打开 word

Kali Linux是一款专为网络安全领域而设计的操作系统,它集成了大量的安全工具,帮助用户进行网络渗透测试和安全评估。作为一款功能强大的操作系统,Kali Linux可以满足用户在网络安全领域的各种需求,包括渗透测试、漏洞分析、数字取…

hooks useModule自定义hooks (二次封装AgGridReact ag-table)自定义表头,自定义表头搜索

场景业务: 多次运用AgGridReact的table 列表 思路: 运用自定义hooks进行二次封装: 通用配置例如:传参的参数,传参的url,需要缓存的key这些键值类 定制化配置例如:需要对table 的一些定制化传…

SpringBoot最简单方式实现自定义异常页面(404)

最简单的方式实现所有自定义异常页面(如 404、500 等)是通过 静态资源文件 或 模板引擎 来实现。 方法 1:使用静态资源文件(最简单) Spring Boot 默认会在 src/main/resources/static 或 src/main/resources/public …

django下防御race condition漏洞(竞争型漏洞)

目录 竞争型漏洞 概念 常见类型及示例 环境搭建 ​编辑漏洞复现 ucenter/1/ ucenter/2/ ucenter/3/ ucenter/4/ 总结 悲观锁 乐观锁 竞争型漏洞 概念 竞争型漏洞,也称为竞态条件漏洞(Race Condition Vulnerability),…

用Python写一个算24点的小程序

一、运行界面 二、显示答案——递归介绍 工作流程&#xff1a; 1. 基本情况&#xff1a;函数首先检查输入的数字列表 nums 的长度。如果列表中只剩下一个数字&#xff0c;它会判断这个数字是否接近 24&#xff08;使用 abs(nums[0] - 24) < 1e-10 来处理浮点数精度问题&…

PostgreSQL 18新特性之虚拟生成列

PostgreSQL 12 提供了生成列&#xff08;GENERATED ALWAYS AS STORED&#xff09;功能&#xff0c;但是只能支持存储型的生成列&#xff0c;需要占用存储空间&#xff0c;更新成本高。 为此&#xff0c;PostgreSQL 18 即将引入一个新的增强&#xff1a;虚拟生成列。这种类型的…

GitHub上传项目

总结&#xff08;有基础的话直接执行这几步&#xff0c;就不需要再往下看了&#xff09;&#xff1a; git init 修改git的config文件&#xff1a;添加:[user]:name你的github用户名 email你注册github的用户名 git branch -m master main git remote add origin 你的URL gi…

常见排序算法深度评测:从原理到10万级数据实战

常见排序算法深度评测&#xff1a;从原理到10万级数据实战 摘要 本文系统解析冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序和基数排序8种经典算法&#xff0c;通过C语言实现10万随机数排序并统计耗时。测试显示&#xff1a;快速排序综合性能最优&…

动态规划填表技巧:固定最后一个数 vs 固定倒数第二个数

在动态规划中&#xff0c;填表时固定最后一个数还是倒数第二个数&#xff0c;取决于问题的定义和状态转移方程的设计。 目录 1. 固定最后一个数 适用场景 特点 示例 2. 固定倒数第二个数 适用场景 特点 示例 3. 固定最后一个数与倒数第二个数的对比 4. 总结 1. 固定最…

【C】链式二叉树算法题2

目录 1 另一棵树的子树 1&#xff09; 题目描述 示例1&#xff1a; 示例2&#xff1a; 2&#xff09; 算法解析 3&#xff09; 代码 2 二叉树的遍历 1&#xff09; 问题描述 2&#xff09; 算法解析 3&#xff09; 代码 3 总结 1 另一棵树的子树 leetcode链接…

配置Hadoop集群

Hadoop的运行模式 本地运行&#xff1a;在一台单机上运行&#xff0c;没有分布式文件系统&#xff0c;直接读写本地操作系统的文件系统。特点&#xff1a;不对配置文件进行修改&#xff0c;Hadoop 不会启动 伪分布式&#xff1a;也是在一台单机上运行&#xff0c;但用不同的 …

python办公自动化--数据可视化(pandas+matplotlib)--生成条形图和饼状图

前言 前几天我们学习了pandas读取数据&#xff0c;还学习了如何用patplotlib绘制柱状图和折线图。 今天我们继续学习&#xff0c;如何绘制条形图和饼状图。 一、课程回顾-pandas读取数据 1.示例数据文件 这里我们用到的依旧是d盘底下的这个excel工作簿&#xff0c;这个工作簿…

基于大模型的结节性甲状腺肿诊疗全流程预测与方案研究报告

目录 一、引言 1.1 研究背景与目的 1.2 研究意义 1.3 国内外研究现状 二、大模型预测原理与方法 2.1 相关大模型概述 2.2 数据收集与预处理 2.3 模型训练与验证 三、术前预测与评估 3.1 结节性质预测 3.1.1 良恶性判断 3.1.2 与传统诊断方法对比 3.2 手术风险预测…

不同开发语言对字符串的操作

一、字符串的访问 Objective-C: 使用 characterAtIndex: 方法访问字符。 NSString *str "Hello, World!"; unichar character [str characterAtIndex:0]; // 访问第一个字符 H NSLog("%C", character); // 输出: H NSString 内部存储的是 UTF-16 编…

Java开发者如何接入并使用DeepSeek

目录 一、准备工作 二、添加DeepSeek SDK依赖 三、初始化DeepSeek客户端 四、数据上传与查询 五、数据处理与分析 六、实际应用案例 七、总结 【博主推荐】&#xff1a;最近发现了一个超棒的人工智能学习网站&#xff0c;内容通俗易懂&#xff0c;风格风趣幽默&#xff…

S19文件格式详解:汽车ECU软件升级中的核心镜像格式

文章目录 引言一、S19文件格式的起源与概述二、S19文件的核心结构三、S19在汽车ECU升级中的应用场景四、S19与其他格式的对比五、S19文件实例解析六、工具链支持与安全考量七、未来趋势与挑战结语引言 在汽车电子控制单元(ECU)的软件升级过程中,S19文件(也称为Motorola S-…