当前位置: 首页 > 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__ 连接起来的链,用于实现属性和方法的查找和继承。

相关文章:

  • RNN做中文分词
  • HTML实现的2048游戏
  • 【JVM】- 垃圾回收
  • C++学习-入门到精通【17】自定义的模板化数据结构
  • 亚马逊云科技 Amazon Pinpoint 解决方案:构建智能全渠道互动平台,重塑用户增长体验
  • Leetcode 3577. Count the Number of Computer Unlocking Permutations
  • 特殊工业镜头百科
  • Java单列模式总结及实现
  • 高考志愿填报,如何查询高校历年录取分数线?
  • 哈希表与unordered_set和unordered_map的实现
  • ESP8266自动浇水系统
  • 寄存器被改写问题总结
  • 408第一季 - 数据结构 - 折半查找与二叉排序树
  • 校园导航系统核心技术解析:高精度定位与 AR 实景导航的应用实践
  • 【Pandas】pandas DataFrame isna
  • 多光谱图像技术在苗期作物与杂草识别中的研究进展
  • OkHttp 中实现断点续传 demo
  • gRPC、WebSocket 与 HTTP 的核心区别对比
  • 【JavaScript】 HTTP Cookie 核心知识梳理与常用的封装实现
  • 学校招生小程序源码介绍
  • 珠宝首饰商城网站建设/域名注册查询阿里云
  • 怎么样查看网站开发语言/文员短期电脑培训
  • 纳森网络做网站多少钱/广东做seo的公司
  • 做网站公司高端/免费代理浏览网页
  • 做网站游戏需要什么/百度客服人工在线咨询
  • 做网站怎么赚钱滑县电/如何发布一个网站