当前位置: 首页 > news >正文

深入解析 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 运行机制的基础。

相关文章:

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

原型和原型链是 JavaScript 中实现对象继承和属性查找的核心机制。为了更深入地理解它们,我们需要从底层原理、实现机制以及实际应用等多个角度进行分析。 1. 原型(Prototype) 1.1 什么是原型? 每个 JavaScript 对象&#xff08…...

关于AI数据分析可行性的初步评估

一、结论:可在部分环节嵌入,无法直接处理大量数据 1.非本地部署的AI应用处理非机密文件没问题,内部文件要注意数据安全风险。 2.AI(指高规格大模型)十分适合探索性研究分析,对复杂报告无法全流程执行&…...

回归预测 | Matlab实现GWO-BP-Adaboost基于灰狼算法优化BP神经网络结合Adaboost思想的回归预测

回归预测 | Matlab实现GWO-BP-Adaboost基于灰狼算法优化BP神经网络结合Adaboost思想的回归预测 目录 回归预测 | Matlab实现GWO-BP-Adaboost基于灰狼算法优化BP神经网络结合Adaboost思想的回归预测回归效果基本介绍GWO-BP-Adaboost:基于灰狼算法优化BP神经网络结合Adaboost思想…...

ARM Cortex-M 内存映射详解:如何基于寄存器直接读写 寄存器映射方式编码程序 直接操作硬件寄存器来控制 MCU

ARM Cortex-M 的系统映射空间 ​ 在 STM32 等 ARM Cortex-M 系列 MCU 中,内存地址空间按照 存储功能 进行了严格划分,包括 Flash(程序存储)、RAM(数据存储)、外设寄存器(GPIO、UART、SPI 等&am…...

深度学习实战车辆目标跟踪与计数

本文采用YOLOv8作为核心算法框架,结合PyQt5构建用户界面,使用Python3进行开发。YOLOv8以其高效的实时检测能力,在多个目标检测任务中展现出卓越性能。本研究针对车辆目标数据集进行训练和优化,该数据集包含丰富的车辆目标图像样本…...

django中视图作用和视图功能 以及用法

在 Django REST Framework(DRF)中,视图(View)是处理 HTTP 请求并返回响应的核心组件。DRF 提供了多种视图类,适用于不同的场景和需求。以下是 DRF 中常见的视图类及其作用、使用方法的详细说明: 一、DRF 视图的分类 DRF 的视图可以分为以下几类: 基于函数的视图(Func…...

【每日学点HarmonyOS Next知识】输入框自动获取焦点、JS桥实现方式、Popup设置全屏蒙版、鼠标事件适配、Web跨域

1、HarmonyOS TextInput或TextArea如何自动获取焦点? 可以使用 focusControl.requestFocus 对需要获取焦点的组件设置焦点,具体可以参考文档: https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-universal-attribut…...

【学习思维模型】

学习思维模型 一、理解类模型二、记忆类模型三、解决问题类模型四、结构化学习模型五、效率与习惯类模型六、高阶思维模型七、实践建议八、新增学习思维模型**1. 波利亚问题解决四步法****2. 主动回忆(Active Recall)****3. 鱼骨图(因果图/Ishikawa Diagram)****4. MECE原则…...

MyBatis-Plus分页控件使用及使用过程发现的一个坑

最近维护一个旧项目的时候,出现了一个BUG,经排查后发现是Mybatis-plus分页控件使用的时候需要注意的一个问题,故在本地使用MybatisPlus模拟出现了一下这个问题。 首先,先说一下MyBatis-Plus的使用: 1)引入…...

STM32的APB1和APB2的区别

STM32微控制器中的APB1和APB2的区别 STM32微控制器中的APB1和APB2是两种不同的外设总线,主要区别在于时钟速度、连接的外设以及用途。以下是它们的详细对比: 1. 时钟速度 APB1 (Advanced Peripheral Bus 1): 低速总线,时钟频率通常为系统时钟…...

JS一些小知识点

一、|| 运算符 plain this.ctx.body { type: type || 0, // ||在此处用法用于默认值填充,判断是否传参或该值是否存在,如果不存在就使用||后买你的值作为默认值 code: code || 0, msg: msg || SUCCESS, data: data || {}, ...others }; 二、trim() 方…...

手写Tomcat:实现基本功能

首先,Tomcat是一个软件,所有的项目都能在Tomcat上加载运行,Tomcat最核心的就是Servlet集合,本身就是HashMap。Tomcat需要支持Servlet,所以有servlet底层的资源:HttpServlet抽象类、HttpRequest和HttpRespon…...

C#变量与变量作用域详解

一、变量基础 1. ‌声明与初始化‌ 声明语法‌&#xff1a;<数据类型> <变量名>&#xff08;如 int age; string name&#xff09;‌初始化要求‌&#xff1a; 1、 类或结构体中的字段变量&#xff08;全局变量&#xff09;‌无需显式初始化‌&#xff0c;默认值…...

SV学习笔记——数组、队列

一、定宽数组 定宽数组是静态变量&#xff0c;编译时便已经确定其大小&#xff0c;其可以分为压缩定宽数组和非压缩定宽数组:压缩数组是定义在类型后面&#xff0c;名字前面;非压缩数组定义在名字后面。Bit [7:0][3:0] name; bit[7:0] name [3:0]; 1.1定宽数组声明 数组的声…...

API调试工具的无解困境:白名单、动态IP与平台设计问题

引言 你是否曾经在开发中遇到过这样的尴尬情形&#xff1a;你打开了平台的API调试工具&#xff0c;准备一番操作&#xff0c;结果却发现根本无法连接到平台&#xff1f;别急&#xff0c;问题出在调试工具本身。今天我们要吐槽的就是那些神奇的开放平台API调试工具&#xff0c;…...

Git清理本地残留的、但已经在服务器上被删除的分支

要筛选出已经被服务器删除的本地分支&#xff0c;并在本地删除这些分支&#xff0c;可以按照以下步骤进行操作&#xff1a; 步骤 1: 获取远程分支信息&#xff0c;确保本地的远程分支信息是最新的&#xff1a; git fetch -p步骤 2: 列出本地分支和远程分支&#xff1a; git …...

HTTPS实现内容加密的逻辑

加密过程 使用非对称加密&#xff0c;网站生成公钥和私钥浏览器获取到网站公钥&#xff08;通过验证和解析CA证书&#xff09;&#xff0c;随即生成一串字符串&#xff0c;然后使用公钥加密&#xff0c;发送给网站。网站用私钥将加密内容解析&#xff0c;然后使用这串字符串对…...

使用vue3.0+electron搭建桌面应用并打包exe

使用vue3.0electron搭建桌面应用并打包exe_如何使用electron将vue3vite开发完的项目打包成exe应用程序-CSDN博客...

JSAR 基础 1.2.1 基础概念_空间小程序

JSAR 基础 1.2.1 基础概念_空间小程序 空间空间自由度可嵌入空间空间小程序 最新的技术进展表明&#xff0c;官网之前的文档准备废除了&#xff0c;基于xsml的开发将退出历史舞台&#xff0c;three.js和普通web结合的技术将成为主导。所以后续学习请移步three.js学习路径&#…...

mysql练习

创建数据库db_ck&#xff0c;再创建表t_hero&#xff0c;将四大名著中的主要人物都插入这个表中&#xff0c;将实现过程中sql提交上上来 1、创建数据库db_ck mysql> create database db_ck; 2、创建表t_hero mysql> use db_ck Database changed mysql> create table …...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

Redis数据倾斜问题解决

Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中&#xff0c;部分节点存储的数据量或访问量远高于其他节点&#xff0c;导致这些节点负载过高&#xff0c;影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral&#xff08;热门工具 Ruff 的开发者&#xff09;推出的下一代高性能 Python 包管理器和构建工具&#xff0c;用 Rust 编写。它旨在解决传统工具&#xff08;如 pip、virtualenv、pip-tools&#xff09;的性能瓶颈&#xff0c;同时…...

Fabric V2.5 通用溯源系统——增加图片上传与下载功能

fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)

一、OpenBCI_GUI 项目概述 &#xff08;一&#xff09;项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台&#xff0c;其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言&#xff0c;首次接触 OpenBCI 设备时&#xff0c;往…...

uniapp 小程序 学习(一)

利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 &#xff1a;开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置&#xff0c;将微信开发者工具放入到Hbuilder中&#xff0c; 打开后出现 如下 bug 解…...

认识CMake并使用CMake构建自己的第一个项目

1.CMake的作用和优势 跨平台支持&#xff1a;CMake支持多种操作系统和编译器&#xff0c;使用同一份构建配置可以在不同的环境中使用 简化配置&#xff1a;通过CMakeLists.txt文件&#xff0c;用户可以定义项目结构、依赖项、编译选项等&#xff0c;无需手动编写复杂的构建脚本…...