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

JavaScript 原型链那些事

在讲原型之前我们先来了解一下函数。

在JS中,函数的本质就是对象,它与其他对象不同的是,创建它的构造函数与创建其他对象的构造函数不一样。那产生函数对象的构造函数是什么呢?是一个叫做Function的特殊函数,通过newFunction 产生的对象就是一个函数。

function f1() {}
//上面的函数等同于:
var f1 = new Function();function sum(a, b) {return a + b;
}
//上面的函数等同于:
var sum = new Function("a", "b", "return a + b");//前面的是函数形参名,最后一个参数是函数体

当一个函数被创建后,这个函数就会自动附带一个属性prototype,它就是一个Object对象,代表着函数的原型。也就是说prototype就是原型对象。
原型对象中包含两个属性:constructor和__proto__。constructor这个属性是指创建原型的函数,它指向函数本身。所以有以下关系:
在这里插入图片描述

var Person = function () { };
var p = new Person();    

看这个 new 究竟做了什么?

我们把 new 的过程拆分成以下三步:

  1. var p={}; 也就是说,初始化一个对象p。

  2. p.proto=Person.prototype;

  3. Person.call§;也就是说构造p,也可以称之为初始化p。

总结原型链的工作原理:

1. 原型对象:在JavaScript中,对象可以有一个原型对象,该对象本身也是一个对象。对象的原型对象通过内部属性[[Prototype]]来引用,这个属性在ES5可以通过Object.getPrototypeOf()或__proto__(非标准但被广泛实现的属性)访问。

2. 属性查找:当访问一个对象的属性时,如果该属性在对象自身上不存在,JavaScript 引擎会沿着[[Prototype]]链向上查找,直到找到该属性或到达链的末端。

3. 构造函数的prototype属性:每个函数都有一个prototype属性,指向一个对象,这个对象是使用该构造函数创建的所有实例的原型。

4. 原型链的末端:所有原型链最终都指向Object.prototype,这是内置的Object构造函数的prototype属性。Object.prototype的原型是null,表示原型链的结束。

代码示例:

示例1:原型链的基础

function Person(name) {this.name = name;
}// 为Person构造函数的prototype添加一个方法
Person.prototype.sayHello = function() {console.log("Hello, my name is " + this.name);
};// 创建Person的实例
var person = new Person("Alice");// 调用原型链上的方法
person.sayHello(); // 输出: Hello, my name is Alice// 查看person的原型
console.log(Object.getPrototypeOf(person) === Person.prototype); // 输出: true

示例2:原型链的继承

// 假设我们有一个Animal构造函数
function Animal(species) {this.species = species;
}Animal.prototype.eat = function() {console.log("Animal eats.");
};// Person构造函数继承自Animal
Person.prototype = Object.create(Animal.prototype);
Person.prototype.constructor = Person; // 修复Person实例的constructor属性// 创建Person的实例
var person = new Person("Alice");// 继承自Animal的方法
person.eat(); // 输出: Animal eats.// Person的原型链
console.log(person.__proto__ === Person.prototype); // 输出: true
console.log(person.__proto__.__proto__ === Animal.prototype); // 输出: true
console.log(person.__proto__.__proto__.__proto__ === Object.prototype); // 输出: true

示例3:原型链的查找过程

var myObject = {sayHi: function() {console.log("Hi!");}
};var childObject = Object.create(myObject);
childObject.name = "Child";// 调用原型链上的方法
childObject.sayHi(); // 输出: Hi!// 原型链的属性查找
console.log(childObject.hasOwnProperty('sayHi')); // 输出: false
console.log(childObject.hasOwnProperty('name')); // 输出: true

最后有关原型链的注意问题:

  • 原型链的修改:可以在任何时候修改对象的原型,但要注意这可能会影响所有继承自该原型的对象。
  • 性能问题:原型链的深度不宜过长,否则可能会影响属性访问的性能。
  • 构造函数的选择:使用构造函数、Object.create()或其他工厂模式时,要明确原型链的设置。
  • __proto__属性:__proto__属性是特定于某些JavaScript引擎的实现,并非ECMAScript标准的一部分。使用Object.getPrototypeOf()和Object.setPrototypeOf()是更标准和可移植的方法。

原型链,你理解了吗?

相关文章:

  • 3D鸡哥又上开源项目!单图即可生成,在线可玩
  • Spring Boot 学习第八天:AOP代理机制对性能的影响
  • 【Spring Boot 源码学习】初识 ConfigurableEnvironment
  • 数据结构(3.8)——栈的应用
  • gdb调试命令大全
  • 【产品经理】订单处理11-订单修改场景梳理
  • 泛微开发修炼之旅--29用计划任务定时发送邮件提醒
  • RISC-V在当前计算架构中的地位
  • 使用Vue CLI方式创建Vue3.0应用程序
  • 如何在Java项目中实现领域驱动设计(DDD)
  • 2024华为OD机试真题-找数字-(C++/Python)-C卷D卷-200分
  • 【BUUCTF-PWN】7-[第五空间2019 决赛]PWN5
  • 【大模型LLM面试合集】大语言模型基础_激活函数
  • 金斗云 HKMP智慧商业软件 任意用户创建漏洞复现
  • 《Windows API每日一练》6.2 客户区鼠标消息
  • 【347天】每日项目总结系列085(2018.01.18)
  • 5、React组件事件详解
  • CNN 在图像分割中的简史:从 R-CNN 到 Mask R-CNN
  • Dubbo 整合 Pinpoint 做分布式服务请求跟踪
  • Go 语言编译器的 //go: 详解
  • Golang-长连接-状态推送
  • Hibernate【inverse和cascade属性】知识要点
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • Java IO学习笔记一
  • Javascript设计模式学习之Observer(观察者)模式
  • JavaWeb(学习笔记二)
  • PAT A1050
  • QQ浏览器x5内核的兼容性问题
  • Selenium实战教程系列(二)---元素定位
  • Spark学习笔记之相关记录
  • Tornado学习笔记(1)
  • vue:响应原理
  • 成为一名优秀的Developer的书单
  • 容器服务kubernetes弹性伸缩高级用法
  • 如何借助 NoSQL 提高 JPA 应用性能
  • 腾讯优测优分享 | Android碎片化问题小结——关于闪光灯的那些事儿
  • 学习ES6 变量的解构赋值
  • 阿里云ACE认证之理解CDN技术
  • ​LeetCode解法汇总307. 区域和检索 - 数组可修改
  • $$$$GB2312-80区位编码表$$$$
  • (1)Nginx简介和安装教程
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (floyd+补集) poj 3275
  • (Matalb回归预测)PSO-BP粒子群算法优化BP神经网络的多维回归预测
  • (二)hibernate配置管理
  • (附源码)spring boot智能服药提醒app 毕业设计 102151
  • (切换多语言)vantUI+vue-i18n进行国际化配置及新增没有的语言包
  • (一) springboot详细介绍
  • (一)基于IDEA的JAVA基础10
  • (转)socket Aio demo
  • (转)Sql Server 保留几位小数的两种做法
  • .apk 成为历史!
  • .bat文件调用java类的main方法
  • .NET 8.0 中有哪些新的变化?
  • .NET Core 版本不支持的问题