JavaScript 原型与原型链:深入理解 __proto__ 和 prototype 的由来与关系

引言

在 JavaScript 的世界中,原型和原型链是理解这门语言面向对象编程(OOP)机制的核心。不同于传统的基于类的语言如 Java,JavaScript 采用了一种独特的原型继承机制。本文将深入探讨 __proto__ 和 prototype 的由来、关系以及它们在 JavaScript 中的作用。


一、JavaScript 的 OOP 机制

传统的面向对象编程语言(如 Java)具有类、继承、封装和多态等特性。JavaScript 虽然也支持 OOP,但其实现方式却大不相同。

1.1 没有类的 JavaScript

在 ES6 之前,JavaScript 并没有 class 关键字。为了实现类似类的功能,开发者通常使用构造函数和原型来模拟类的行为。例如:

// Java 中的类定义
public class Puppy {int puppyAge;public Puppy(int age) {puppyAge = age;}public void say() {System.out.println("汪汪汪");}
}

而在 JavaScript 中,我们通过函数来模拟类:

// JavaScript 中的构造函数模拟类
function Person(name, age) {this.name = name;this.age = age;
}

1.2 对象字面量的局限性

虽然可以通过对象字面量创建对象,但当需要创建多个相似对象时,这种方式显得非常繁琐:

var Person = {name: '吉他胡',hobbies: ['弹吉他', '弹钢琴'],
}var pll = {name: '皮乐乐',hobbies: ['弹吉他', '弹钢琴'],
}

为了解决这个问题,JavaScript 引入了构造函数和原型的概念。


二、构造函数与原型

2.1 构造函数

构造函数是 JavaScript 中模拟类的关键。通过约定俗成,构造函数的名称首字母大写:

function Person(name, age) {this.name = name;this.age = age;
}

2.2 prototype 属性

每个函数都有一个 prototype 属性,它是一个对象,用于存储共享的属性和方法。通过将方法定义在 prototype 上,可以避免每次实例化对象时重复创建方法:

Person.prototype.sayHello = function() {console.log(`hello, my name is ${this.name}`);
}

2.3 __proto__ 属性

每个对象都有一个私有属性 __proto__,它指向构造函数的 prototype 对象。例如:

let hu = new Person('吉他胡', 18);
console.log(hu.__proto__ === Person.prototype); // true

__proto__ 是对象与构造函数之间的桥梁,也是原型链实现的基础。


三、原型链

3.1 原型链的概念

JavaScript 中的继承是通过原型链实现的。当访问一个对象的属性或方法时,如果对象本身没有该属性,JavaScript 会沿着 __proto__ 向上查找,直到找到该属性或到达原型链的顶端(Object.prototype),最终指向 null

console.log(hu.toString()); // 调用的是 Object.prototype.toString

3.2 修改原型链

__proto__ 可以动态修改,从而改变对象的原型链:

var a = {name: '孔子',country: '中国',
};
hu.__proto__ = a;
console.log(hu.country); // 输出:中国

3.3 原型链的终点

原型链的顶端是 Object.prototype,其 __proto__ 指向 null

console.log(Object.prototype.__proto__); // null

四、new 的过程

当我们使用 new 关键字创建对象时,JavaScript 会执行以下步骤:

  1. 创建一个空对象 {}
  2. 运行构造函数,并将 this 指向这个空对象。
  3. 将对象的 __proto__ 指向构造函数的 prototype
  4. 返回构造完成的对象。
let hu = new Person('吉他胡', 18);

五、prototype 与 __proto__ 的关系

  • prototype:是函数特有的属性,指向构造函数的原型对象。
  • __proto__ :是对象特有的属性,指向构造函数的 prototype 对象。

它们的关系可以用以下代码验证:

console.log(Person.prototype.constructor === Person); // true
console.log(hu.__proto__ === Person.prototype); // true

六、总结

  1. JavaScript 没有类,而是通过构造函数和原型模拟类的行为。
  2. prototype 是函数特有的属性,用于定义共享的属性和方法。
  3. __proto__  是对象特有的属性,用于构建原型链。
  4. 原型链 是 JavaScript 实现继承的机制,通过 __proto__ 向上查找属性和方法。
  5. new 关键字 通过构造函数创建对象,并建立原型链关系。

理解原型和原型链是掌握 JavaScript 面向对象编程的关键。虽然 ES6 引入了 class 语法,但其底层仍然是基于原型的实现。希望本文能帮助你更好地理解 JavaScript 的原型机制!

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

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

相关文章

Linux非管理员用户安装python环境

目录 1. 下载2. 解压3. 配置并指定安装路径(本地用户目录)4. 编译(不安装系统目录)5. 安装到本地用户目录6. 添加 Python 到环境变量7. 验证安装是否成功 1. 下载 版本根据需要自行指定 cd /tmp wget https://www.python.org/ft…

猎板PCB:建滔PCB板材怎么样?

在电子元器件的精密世界中,PCB板材如同骨骼般支撑着整个产品的性能与寿命。面对市场上琳琅满目的品牌选择,建滔积层板凭借三十余年技术沉淀,逐渐成为行业工程师与采购方口中的“品质代名词”。今天,我们不谈参数堆砌,只…

ONLYOFFICE协作空间3.1.1 企业版 介绍及部署说明:家庭云计算专家

ONLYOFFICE协作空间3.1企业版是一款专为深度集成需求设计的开源解决方案,其核心功能聚焦于安全性与灵活性。该版本支持私有化部署,允许企业将协作空间嵌入自有服务器并实现品牌定制化,满足对数据主权和品牌一致性的严苛要求。 在安全方面&…

接IT方案编写(PPT/WORD)、业务架构设计、投标任务

1、IT 方案编写(PPT/WORD)​ 定制化方案:根据客户需求,提供涵盖云计算、大数据、人工智能等前沿技术领域的 PPT/WORD 方案编写服务,精准提炼核心价值,呈现专业技术内容。​ 逻辑清晰架构:采用…

前端面试之变量与数据类型

目录 一、声明变量 (1)let (2)const (3)var var、let 和 const 的作用域差异 二、数据类型 (1)基本类型 undefined和null String 模板字符串拼接: number和b…

python queue

Python中的queue模块提供了多种队列实现,主要用于线程间安全通信。以下是主要用法: 基本队列类型: Queue:先进先出(FIFO)队列LifoQueue:后进先出(LIFO)队列,即栈PriorityQueue:优先级队列 常用方…

Linux驱动:class_create、device_create

udev是什么 动态管理设备文件 传统的 Linux 系统通过静态创建 /dev 目录下的设备文件(如早期的 mknod 命令),但现代系统中硬件设备(如 USB 设备、存储设备、串口等)热插拔频繁,udev 可实时响应设备事件&…

【vLLM 学习】Cpu Offload Lmcache

vLLM 是一款专为大语言模型推理加速而设计的框架,实现了 KV 缓存内存几乎零浪费,解决了内存管理瓶颈问题。 更多 vLLM 中文文档及教程可访问 →https://vllm.hyper.ai/ *在线运行 vLLM 入门教程:零基础分步指南 源码 examples/offline_inf…

基于深度强化学习的Scrapy-Redis分布式爬虫动态调度策略研究

在大数据时代,网络数据的采集与分析变得至关重要,分布式爬虫作为高效获取海量数据的工具,被广泛应用于各类场景。然而,传统的爬虫调度策略在面对复杂多变的网络环境和动态的抓取需求时,往往存在效率低下、资源浪费等问…

openlayers实现可拖拽的节点(类似知识图谱)

/** * 本文介绍了实现知识图谱可视化的技术方案,主要分为两个图层实现: * 1、线图层 不拖动 * 2、点图层 需要拖动 */ 线图层 - 负责绘制静态连接线,使用LineString创建线要素并添加到矢量图层; // 线图层 export function add…

酷黑NBA足球赛事直播源码体育直播M39模板赛事源码

源码名称:NBA足球赛事直播源码酷黑体育直播M39模板赛事源码 开发环境:帝国cms7.5 空间支持:phpmysql 带软件采集,可以挂着自动采集发布,无需人工操作! 演示地址:https://www.52muban.com/shop…

Verilog编程技巧01——如何编写三段式状态机

前言 Verilog编程技巧系列文章将聚焦于介绍Verilog的各种编程范式或者说技巧,编程技巧和编程规范有部分重合,但并非完全一样。规范更注重编码的格式,像变量命名、缩进、注释风格等,而编程技巧则更偏重更直观易读、更便于维护、综合…

豆包和deepseek 元宝 百度ai区别是什么

豆包、DeepSeek、元宝和百度 AI 有以下区别: 开发公司 豆包5:由字节跳动公司基于云雀模型开发。DeepSeek4:是深度求索打造的开源多模态大模型。元宝1:是腾讯混元模型的落地产品,整合了 DeepSeek - R1 与混元模型。百…

网页端 js 读取发票里的二维码信息(图片和PDF格式)

起因 为了实现在报销流程中,发票不能重用的限制,发票上传后,希望能读出发票号,并记录发票号已用,下次不再可用于报销。 基于上面的需求,研究了OCR 的方式和读PDF的方式,实际是可行的&#xff…

读文献先读图:GO弦图怎么看?

GO弦图(Gene Ontology Chord Diagram)是一种用于展示基因功能富集结果的可视化工具,通过弦状连接可以更直观的展示基因与GO term(如生物过程、分子功能等)之间的关联。 GO弦图解读 ①内圈连线表示基因和生物过程之间的…

pandas随笔

主要操作两个对象:一维带标签数组 和 二维表格DataFrame 一维带标签数组Series pd.Series([1, 3, 5, np.nan, 6, 8]) ,结果如下: 可指定索引,pd.Series([1, 3, 5], index[a, b, c]) 二维表格DataFrame 创建时需要指定列名&a…

java教程笔记(十一)-泛型

Java 泛型(Generics)是 Java 5 引入的重要特性之一,它允许在定义类、接口和方法时使用类型参数。泛型的核心思想是将类型由具体的数据类型推迟到使用时再确定,从而提升代码的复用性和类型安全性。 1.泛型的基本概念 1. 什么是泛…

力扣刷题(第四十九天)

灵感来源 - 保持更新,努力学习 - python脚本学习 反转链表 解题思路 迭代法:通过遍历链表,逐个改变节点的指针方向。具体步骤如下: 使用三个指针:prev(初始为None)、curr(初始为…

设置应用程序图标

(1)找一张图片 (2)然后转ico图片 在线生成透明ICO图标——ICO图标制作 验证16x16就可以 降低exe大小 (3) 在xxx.pro修改 添加 (4) 删除 build 和 xxxpro_user文件 (5)编译project 和运行xx.exe (6)右键 设置快捷方式

免费wordpress模板下载

西瓜红色的免费wordpress模板,简洁实用又容易上手,适合新手使用。 下载 https://www.waimaoyes.com/moban/2231.html