JavaScript 原型链:一场家族继承的奇妙之旅

想象一下,你有一个大家族,每个家族成员都有自己的个性和特点。在这个家族中,成员之间存在着一种特殊的传承关系:长辈的财产和智慧可以被子孙后代继承。在 JavaScript 的世界里,这种传承关系就是通过 原型链 来实现的。

一、家族的秘密:原型

每个 JavaScript 对象都有一个特殊的属性,叫做 原型。这个原型就像家族中的长辈,它身上拥有着一些共有的属性和方法。当我们创建一个新对象时,这个新对象就会继承它原型上的所有属性和方法。

举个例子,假设我们有一个 Person 构造函数:

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

通过这个构造函数,我们可以创建很多个 Person 对象。这些对象都拥有 nameage 属性。但是,如果我们想让所有的 Person 对象都拥有一个 sayHello 方法,该怎么办呢?

我们可以将 sayHello 方法添加到 Person 的原型上:

Person.prototype.sayHello = function() {console.log('Hello, my name is ' + this.name);
};

这样,所有由 Person 构造函数创建的对象都能够使用 sayHello 方法了。这就像家族中的长辈传授给子孙后代一门独特的技能一样。

二、家族的传承:原型链

原型链就像是一条长长的链子,将家族中的成员连接起来。当我们访问一个对象的属性或方法时,JavaScript 引擎会沿着这条链子向上查找,直到找到匹配的属性或方法,或者到达链子的尽头。

let person1 = new Person('Alice', 25);
person1.sayHello(); // 输出:Hello, my name is Alice

当我们调用 person1.sayHello() 时,JavaScript 引擎会先在 person1 对象本身查找 sayHello 方法,如果没有找到,就会沿着原型链向上查找,最终在 Person.prototype 上找到 sayHello 方法并执行。

三、家族的变迁:原型链的应用

原型链在 JavaScript 中有着广泛的应用:

  • 创建自定义对象: 通过原型链,我们可以创建各种各样的自定义对象,比如 AnimalCarHouse 等。
  • 实现继承: 原型链是 JavaScript 实现继承的主要方式。我们可以通过原型链将一个对象的属性和方法继承给另一个对象。
  • 模拟类: 虽然 JavaScript 没有传统的类,但是我们可以利用原型链来模拟类的行为。

四、家族的秘密花园:原型链的深入

上文我们把 JavaScript 的原型链比喻成一个家族的传承,通过原型链,家族成员可以继承祖先的财产和智慧。现在,让我们深入这个家族的秘密花园,探索更多关于原型链的奥秘。

1、原型链的查找过程

当我们访问一个对象的属性或方法时,JavaScript 引擎会沿着原型链向上查找,直到找到匹配的属性或方法,或者到达链的尽头(null)。这个查找过程就像我们查找家族族谱一样,一层一层向上寻找。

function Person(name) {this.name = name;
}Person.prototype.sayHello = function() {console.log('Hello, my name is ' + this.name);
};let person1 = new Person('Alice');
person1.sayHello(); // 输出:Hello, my name is Alice

在这个例子中,当我们调用 person1.sayHello() 时,JavaScript 引擎会:

  1. 在 person1 对象本身查找 sayHello 方法: 找不到。
  2. 沿着 proto 属性向上查找,找到 Person.prototype: 找到 sayHello 方法。
  3. 执行 sayHello 方法: 输出 “Hello, my name is Alice”。

2、原型链与构造函数的关系

构造函数是创建对象的模板,每个构造函数都有一个 prototype 属性,指向它的原型对象。原型对象上的属性和方法可以被所有由这个构造函数创建的对象所继承。

function Person(name) {// ...
}Person.prototype // 指向 Person 的原型对象

3、原型链与 proto 属性

每个对象都有一个 proto 属性,指向它的原型对象。通过 proto 属性,我们可以手动修改一个对象的原型。

let person1 = new Person('Alice');
console.log(person1.__proto__ === Person.prototype); // true

4、原型链的尽头

原型链的尽头是 null。当 JavaScript 引擎沿着原型链向上查找时,如果到达了 null,说明没有找到匹配的属性或方法。

5、原型链的缺陷

  1. 原型污染
Array.prototype.myCustomMethod = function() {// ...
};

在上面的例子中,会导致所有的数组对象都拥有一个额外的 myCustomMethod 方法,可能会造成意想不到的副作用。

  • 解决方案:
    • 使用 ES6 的 Object.definePropertyObject.seal 等方法来保护对象。
    • 尽量避免直接修改内置对象的原型。
  1. 性能问题
  • 频繁的原型链查找可能会影响性能,尤其是在大型对象或复杂的继承结构中。
  • 解决方案:
    • 缓存常用的属性或方法。
    • 优化代码结构,减少不必要的原型链查找。

五、原型链与闭包:相辅相成的 JavaScript 特性

原型链和闭包是 JavaScript 中两个非常重要的概念,它们在实现一些高级特性时,经常会相互配合。

1、闭包是什么?

闭包是指在函数内部定义的函数,这个内部函数可以访问外部函数的变量。即使外部函数已经执行完毕,内部函数仍然可以访问这些变量。

2、原型链是什么?

原型链是 JavaScript 中用来实现继承的一种机制。每个对象都有一个 __proto__ 属性,指向它的原型对象。当我们访问一个对象的属性时,如果对象本身没有这个属性,就会沿着原型链向上查找,直到找到这个属性或者到达原型链的尽头。

function Animal(name) {this.name = name;
}Animal.prototype.eat = function() {console.log(this.name + ' is eating.');
}function Dog(name, breed) {Animal.call(this, name);this.breed = breed;
}Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.bark = function() {console.log(this.name + ' is barking.');
}

3、原型链与闭包的结合

  1. 私有属性和方法:
  • 通过闭包创建私有变量:我们可以将一些属性和方法定义在闭包内部,使得它们只能在闭包内部访问,从而实现私有化。
  • 利用原型链共享公共方法:将公共的方法定义在原型对象上,所有实例都可以共享。
function Person(name) {let age = 0; // 私有属性,只能在闭包内部访问this.name = name;this.sayHello = function() {console.log(`Hello, my name is ${this.name}, I am ${age} years old.`);};this.setAge = function(newAge) {age = newAge;};
}

在上面的例子中,age 是一个私有属性,只能通过 setAge 方法来修改。sayHello 方法则是一个公共方法,可以通过原型链被所有实例共享。

function Counter() {let count = 0;this.increment = function() {count++;}this.getCount = function() {return count;}
}

在上面的例子中,展示了如何使用闭包来实现私有变量,只能通过 incrementgetCount 方法来修改、获取 count 变量。

  1. 模块化:
  • 使用闭包创建模块:我们可以使用闭包来创建一个模块,将模块的内部状态隐藏起来。
  • 利用原型链共享模块的方法:将模块的方法定义在原型对象上,让多个模块共享这些方法。
function createModule() {let privateData = 'This is private data';return {publicMethod: function() {console.log(privateData);}};
}let module1 = createModule();
module1.publicMethod(); // 输出:This is private data

六、扩展到 ES6+:类语法与原型链

ES6 引入了 class 语法,让 JavaScript 的面向对象编程更加直观。然而,class 只是语法糖,底层仍然是基于原型链实现的

1、class 语法与原型链的关系

  • class 关键字:
    • class 关键字定义了一个类,这个类本质上是一个构造函数。
    • 类中的方法会自动添加到类的原型上。
  • constructor 方法:
    • constructor 方法用于初始化对象,类似于传统的构造函数。
  • extends 关键字:
    • extends 关键字用于实现继承,子类会继承父类的原型。
// ES5 的写法
function Person(name) {this.name = name;
}
Person.prototype.sayHello = function() {console.log('Hello, my name is ' + this.name);
};// ES6 的写法
class Person {constructor(name) {this.name = name;}sayHello() {console.log(`Hello, my name is ${this.name}`);}
}

这两段代码本质上是等价的。在 ES6 的写法中,sayHello 方法被自动添加到 Person.prototype 上。

2、继承

// ES5 的写法
function Student(name, grade) {Person.call(this, name);this.grade = grade;
}
Student.prototype = Object.create(Person.prototype);
Student.prototype.study = function() {console.log('I am studying.');
};// ES6 的写法
class Student extends Person {constructor(name, grade) {super(name);this.grade = grade;}study() {console.log('I am studying.');}
}
  • extends 关键字表示 Student 类继承自 Person 类。
  • super 关键字用于调用父类的构造函数。

七、总结

JavaScript 原型链就像是一个家族的传承,将对象的属性和方法连接起来,使得 JavaScript 对象之间能够共享特性,即通过将对象的属性和方法连接起来,实现了对象的继承和复用。虽然 ES6 引入了 class 语法,但底层仍然是基于原型链实现的。深入理解原型链,不仅有助于我们写出更优雅的代码,还能更好地掌握 JavaScript 的运行机制,为我们构建复杂的 Web 应用程序打下坚实的基础。

原文地址

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【Go语言】| 第1课:Golang安装+环境配置+Goland下载

😎 作者介绍:我是程序员洲洲,一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主。 🤓 同时欢迎大家关注其他专栏,我将分享Web前后端开发、人工智能、机器学习、深…

程序猿要失业了,一行代码没写,1小时嘴搓了一个图片分割插件(好看又好用)

如题,一行代码没写,使用 AI 编程工具实现了一个浏览器图片分割插件的开发,先看效果吧( Chrome商店上架审核中~ ) 支持点击,拖拽,直接粘贴,还支持预览,次数统计&#xff0…

基于SpringBoot+Vue实现新零售商城系统

作者主页:编程千纸鹤 作者简介:Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参…

【湖南】《湖南省省直单位政府投资信息化项目预算编制与财政评审工作指南(试行)》湘财办〔2024〕10号-省市费用标准解读系列06

2024年4月12日,湖南省财政厅发布实施《湖南省省直单位政府投资信息化项目预算编制与财政评审工作指南(试行)》湘财办〔2024〕10号(以下简称“10号文”),该文件旨在指导提高湖南省直单位政府投资信息化项目预…

攻防靶场(28):通过SNMP进行信息收集 JOY

目录 1.侦查 1.1 获取目标网络信息:IP地址 1.2 主动扫描:扫描IP地址块 1.3 收集受害者主机信息:软件 2. 数据窃取 2.1 通过备用协议窃取:通过未加密的非C2协议窃取 2.2 通过备用协议窃取:通过未加密的非C2协议窃取 3. …

DCDC-LLC谐振电路Q值与系统增益变化相反的原因

1.谐振电路的Q值定义 LLC电路的Q值定义: 它表述的是整个电路的能量存储与耗散的关系。损耗越小,Q值越大,损耗越大,Q值越小。 Q的另一种写法是: 这个公式来由,因为谐振频率: 所以: 所以&#…

【JAVA毕业设计】基于Vue和SpringBoot的图书馆管理系统

本文项目编号 T 044 ,文末自助获取源码 \color{red}{T044,文末自助获取源码} T044,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析5.4 用例设计 六、核…

VirtualBox7.0的“网络地址转换(NAT)“ 笔记2400727

VirtualBox7.0的"网络地址转换(NAT)" 每台虚拟机的默认ip都是 10.0.2.15 虚拟机之间不能互通虚拟机能通过主机各ip访问主机(延时高,不稳定), 主机不能直接访问虚拟机, 可以通过端口转发(端口映射)虚拟机能访问宿主机的局域网的其它机器,虚拟机能访问网络, 但不能反过…

PyQt5 详细安装与配置教程及使用

文章目录 Part1:安装 PyQt5Part2:配置 PyQt5 的依赖工具 QtDesigner 和 PyUICPart3:使用QtDesigner设计界面Part4:使用PyUIC将设计好的界面转换为.py文件Part5:通过代码显示ui界面 Part1:安装 PyQt5 需要安…

10.31.2024刷华为OD C题型

文章目录 HJ26HJ27语法知识记录 10.24.2024刷华为OD C题型(四) - HJ26 HJ27 def get_dict(str1: str):dic_0 {}for ch in str1:if ch not in dic_0:dic_0[ch] 1else:dic_0[ch] 1return dic_0temp input().split() n int(temp[0]) list [] for i in range(n):l…

基于springboot+mybatis美术馆预约管理系统设计和实现以及文档报告

基于springbootmybatis美术馆预约管理系统设计和实现以及文档报告 🍅 作者主页 网顺技术团队 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 🍅 文末获取源码联系方式 📝 🍅 查看下方微信号获取联系方式 承接各…

气象监测软件的程序设计

老师留了个作业,感觉挺有意思,记录一下 文章目录 气象监测软件的程序设计项目指导书(一)基本信息(二)项目目标(三)任务描述(四)指导内容任务 1:根…

漫谈MCU优化:从硬件设计优化到可靠性挑战

1.关于MCU 微控制器(Microcontroller Unit, MCU),是以微处理器为基础,加上存储器以及计数器、I2C、UART等外设模块与接口电路整合的单芯片微型计算机。 ▲MCU实物图 MCU拥有性能好、可编程、灵活度高、功耗低等优点,…

“动态波动”,背离信号与主力动向的完美结合 源码

使用技巧 精准捕捉买卖信号 这款公式它不仅能够精准捕捉买入信号,还能敏锐识别卖出时机。尤其在市场波动不定的震荡行情中,动态波动展现出了其非凡的价值。 多维信号分析 如图所示,动态波动公式全面覆盖了“买”、“卖”、“洗盘”、“阻…

网站架构知识之密钥认证(day020)

1.密钥认证 两个节点,通过密钥形式进行访问,不要输入密码,单向。 应用场景:部分服务使用前要求我们做密钥认证。 1.使用rsa算法创建公钥私钥 ssh-keygen -t rsa /root/.ssh/id_rsa, 私钥地址 /root/.ssh/…

基于Python的智能旅游推荐系统设计与实现

一、摘要 本毕业设计的内容是设计并且实现一个基于Python技术的智能旅游推荐系统。它是在Windows下,以MYSQL为数据库开发平台,使用Python技术进行设计。智能旅游推荐系统的功能已基本实现,主要实现首页,个人中心,用户…

深入计算机语言之C++:模板初阶

🔑🔑博客主页:阿客不是客 🍓🍓系列专栏:从C语言到C语言的渐深学习 欢迎来到泊舟小课堂 😘博客制作不易欢迎各位👍点赞⭐收藏➕关注 一、泛型编程 1.1 引入 C 语言中实现两数交换&a…

O-RAN前传Spilt Option 7-2x

Spilt Option 7-2x 下行比特处理上行比特处理相关文章: Open Fronthaul wrt ORAN 联盟被称为下层拆分(LLS),其目标是提高电信市场的灵活性和竞争力。下层拆分是指无线电单元(RU) 和分布式单元(DU) 之间的拆分。 O-RAN前传接口可以在 eCPRI 上传输。eCPR…

硬件---2电阻---精度、阻值识别、电阻功率、电阻限流、电阻分流、电阻分压

一电阻的阻值识别 1电阻精度问题 电阻精度是指实际电阻值与标称值之间的允许偏差&#xff0c;用于表示电阻的制造误差范围。简单来说&#xff0c;精度越高&#xff0c;实际电阻值越接近标称值。 <1>理解电阻精度 标称值是电阻器上标注的理想数值&#xff0c;比如100Ω。…