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

【面向对象】1. 原型与原型链的概念

文章目录

  • 前言
  • 1. 原型
  • 2. 原型链
  • 3. `__proto__` 与 `Object.getPrototypeOf()‌`
  • ‌4. 构造函数的 prototype 属性与实例的 `__proto__‌`
  • 5. 原型链的终点
  • 6. 继承
  • 7. 验证原型的方法
  • 总结


前言

在 JavaScript 中,每个对象(除了null)都有一个与之关联的原型(prototype)对象。原型对象也是一个对象,它包含可以由特定对象共享的属性和方法。当我们试图访问一个对象的属性时,如果该对象自身没有这个属性,那么 JavaScript 引擎会去该对象的原型上查找,如果原型对象上也没有,那么就会去原型的原型上查找,如此层层向上,直到找到一个匹配的属性或到达原型链的末端(null)。这种查找机制所形成的链式结构被称为原型链。


1. 原型

  • 每个函数(除了箭头函数)都有一个 prototype 属性,这个属性指向一个对象,称为原型对象。
  • 当使用 new 关键字调用构造函数创建实例时,该实例的内部指针(__proto__,现在更推荐使用 Object.getPrototypeOf(obj))会指向构造函数的 prototype 对象。
function Person(name) {this.name = name;
}
// 给Person函数的原型添加方法
Person.prototype.sayHello = function() {console.log(`Hello, my name is ${this.name}`);
};const person1 = new Person('Alice');
person1.sayHello(); // 输出:Hello, my name is Alice

这里,person1 是 Person 的实例。person1 本身没有 sayHello() 方法,所以它会去 Person.prototype 上查找。


2. 原型链

  • 每个对象都有一个原型对象,而原型对象本身也可能有原型对象,这样就形成了一条链。
  • 例如,person1 的原型是 Person.prototype,而 Person.prototype 也是一个对象,它的原型是 Object.prototype(因为Person.prototype 是一个普通对象,由 Object 构造函数创建),而 Object.prototype 的原型是 null,这样就构成了一个原型链:person1 -> Person.prototype -> Object.prototype -> null。
  • 当我们访问 person1.toString() 时,查找过程如下:
    • 首先在 person1 自身查找,没有找到;
    • 然后去 Person.prototype 上查找,也没有;
    • 接着去 Object.prototype 上查找,找到了 toString 方法,于是调用它。

3. __proto__Object.getPrototypeOf()‌

  • __proto__(注意:前后各两个下划线)是对象的一个内部属性,它指向该对象的原型。虽然它在很多环境中可用,但并不是标准的一部分,因此更推荐使用 Object.getPrototypeOf(obj) 来获取对象的原型。
  • 使用 Object.setPrototypeOf(obj, prototype) 可以设置对象的原型,但修改对象的原型可能会带来性能问题,因此应谨慎使用。

‌4. 构造函数的 prototype 属性与实例的 __proto__‌

构造函数的 prototype 属性在创建实例时会被赋值给实例的 __proto__。即:instance.__proto__ === Constructor.prototype

5. 原型链的终点

所有原型链的终点都是 Object.prototype,它是所有对象的原型。而 Object.prototype 的原型是 null。

6. 继承

JavaScript 的继承是通过原型链实现的。子类的原型对象指向父类的一个实例,从而继承父类的属性和方法。

例如,实现继承的一种方式(不推荐使用,仅作为示例):

function Animal(name) {this.name = name;
}
Animal.prototype.speak = function() {console.log(`${this.name} makes a noise.`);
};function Dog(name) {Animal.call(this, name); // 调用父类构造函数
}
// 设置Dog的原型为Animal的实例
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog; // 修复构造函数指向Dog.prototype.bark = function() {console.log(`${this.name} barks.`);
};const dog = new Dog('Rex');
dog.speak(); // 继承自Animal: Rex makes a noise.
dog.bark();  // Rex barks.

在这个例子中,Dog 继承了 Animal。Dog 的实例 dog 的原型链是:dog -> Dog.prototype(也是Animal的一个实例)-> Animal.prototype -> Object.prototype -> null。

注意:现代JavaScript中,更推荐使用 class 和 extends 关键字来实现继承,但其底层仍然是基于原型链。

7. 验证原型的方法

instanceof‌:检测构造函数的 prototype 是否在对象的原型链上。

console.log(alice instanceof Person); // true
console.log(alice instanceof Object); // true

Object.getPrototypeOf()‌:获取对象的 [[Prototype]]。

console.log(Object.getPrototypeOf(alice) === Person.prototype); // true

isPrototypeOf()‌:检测对象是否在另一个对象的原型链上。

console.log(Person.prototype.isPrototypeOf(alice)); // true

总结

  • 原型(prototype)是函数对象的一个属性,它指向一个对象,该对象包含可以由该函数创建的所有实例共享的属性和方法。
  • 每个对象都有一个原型对象(通过 __proto__ 或 Object.getPrototypeOf 访问),对象从原型对象继承属性和方法。
  • 原型链是由原型对象通过 __proto__ 连接起来的链,用于实现属性和方法的查找和继承。
http://www.xdnf.cn/news/965161.html

相关文章:

  • 如何保证RocketMQ消息不丢失
  • TDengine 快速体验(Docker 镜像方式)
  • docker 网络管理
  • 观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
  • MyBatis的#和$符号详解(Java面试)
  • 企业产品网络安全日志6月10日-WAF资费消耗排查
  • 【大模型01---Flash Attention】
  • 常见的http状态码
  • MySQL主从复制实现指南
  • AWS Lambda Python + AWS Secrets Manager + AWS Aurora Mysql
  • AI+预测3D新模型百十个定位预测+胆码预测+去和尾2025年6月10日第104弹
  • 深度学习聊天机器人 需要考虑
  • Linux简单的操作
  • 基于算法竞赛的c++编程(29)类的概念和简单应用
  • v-bind 与 v-model 的区别与联系详解
  • python第48天打卡
  • 通过 VS Code 连接 GitLab 并上传项目
  • 第十四届蓝桥杯_省赛B组(C).冶炼金属
  • 【单片机期末】汇编试卷
  • 64页|PPT|基于华为IPD与质量管理体系融合的研发质量管理:L1-L6分层架构驱动高效运营、标准化质量管理体系
  • 【解密LSTM、GRU如何解决传统RNN梯度消失问题】
  • 详解CNN
  • node+express+jwt+sequelize+mysql+本地服务器部署前端+云服务器公网部署:入门教程
  • 线程与进程(java)
  • 解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
  • 数据库——MongoDB
  • 定时器任务——若依源码分析
  • Python包(Package)详解:模块的高级组织方式
  • DeviceNet转Modbus RTU,为纺织厂生产线赋能
  • uniapp的请求封装,如何避免重复提交请求