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

JS的原型和原型链浅析

原型与原型链

在 JavaScript 中,原型(Prototype)是对象的一种特殊类型,它是所有对象共享属性和方法的机制。每一个 JavaScript 对象都与一个原型对象相关联,并且通过原型链来继承属性和方法。

1. 原型(Prototype)

每个对象在创建时都会有一个内部属性 [[Prototype]],它指向该对象的原型。在 JavaScript 中,原型通常通过 __proto__ 属性访问,或者可以通过 Object.getPrototypeOf() 方法获取。

原型本质上是一个普通对象,拥有可以共享的属性和方法。对象通过它的原型来访问这些共享的属性和方法。

2. 原型链(Prototype Chain)

原型链是一种链式结构,通过一个对象的 [[Prototype]] 属性将多个对象链接起来。当你访问对象的属性时,如果该对象本身没有这个属性,它会沿着原型链查找该属性,直到找到为止。如果原型链的末端仍然没有该属性,则返回 undefined

代码示例

创建对象与原型链
// 构造函数
function Animal(name) {
  this.name = name;
}

// 在原型上定义一个方法
Animal.prototype.sayHello = function() {
  console.log(`Hello, my name is ${this.name}`);
};

// 创建一个 Animal 对象
const dog = new Animal('Dog');

// 通过实例访问原型方法
dog.sayHello();  // Output: Hello, my name is Dog

// 查看dog的原型
console.log(dog.__proto__ === Animal.prototype);  // true

解析:

  1. Animal.prototype 定义了 sayHello 方法,这个方法并不是直接在实例 dog 上定义的,而是通过原型链来访问的。
  2. 当我们调用 dog.sayHello() 时,JavaScript 引擎会先查看 dog 是否有 sayHello 方法,如果没有,则沿着原型链去 Animal.prototype 上找。
  3. 由于 dog 是通过 Animal 构造函数创建的,所以 dog.__proto__Animal.prototype
原型链的查找机制
function Animal(name) {
  this.name = name;
}

Animal.prototype.sayHello = function() {
  console.log(`Hello from ${this.name}`);
};

function Dog(name, breed) {
  Animal.call(this, name);  // 继承 Animal 的属性
  this.breed = breed;
}

// 继承 Animal 的方法
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.bark = function() {
  console.log(`${this.name} says Woof!`);
};

const myDog = new Dog('Max', 'Golden Retriever');

myDog.sayHello(); // Hello from Max
myDog.bark();     // Max says Woof!

解析:

  1. Dog 通过 Object.create(Animal.prototype) 来继承 Animal 的原型方法。
  2. myDog 对象继承了 Animal 的方法 sayHelloDog 的方法 bark
  3. myDog.sayHello() 调用时,JavaScript 引擎沿着原型链查找,首先找到 Dog.prototype 上的 sayHello 方法。
instanceof 运算符

instanceof 用于检查对象是否为某个构造函数的实例。它基于原型链工作,检查对象的原型链中是否有构造函数的 prototype 属性。

console.log(myDog instanceof Dog);   // true
console.log(myDog instanceof Animal); // true
console.log(myDog instanceof Object); // true

解析:

  1. myDog instanceof Dog 返回 true,因为 myDogDog 的实例,且 Dog.prototype 存在于 myDog 的原型链中。
  2. myDog instanceof Animal 也返回 true,因为 Dog.prototype 继承自 Animal.prototype,所以 myDog 的原型链也包含 Animal.prototype

原型的应用场景

1. 方法共享

通过将方法定义在构造函数的原型上,多个实例对象可以共享相同的功能,而不需要每次创建对象时都重新定义方法,从而节省内存空间。

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

// 共享方法
Person.prototype.greet = function() {
  console.log(`Hello, my name is ${this.name}`);
};

const p1 = new Person('Alice');
const p2 = new Person('Bob');

p1.greet(); // Hello, my name is Alice
p2.greet(); // Hello, my name is Bob
2. 模拟继承

原型链机制是 JavaScript 实现继承的一种方式。通过修改构造函数的原型,我们可以实现不同类型之间的继承。

function Shape(name) {
  this.name = name;
}

Shape.prototype.describe = function() {
  console.log(`This is a ${this.name}`);
};

function Circle(name, radius) {
  Shape.call(this, name);
  this.radius = radius;
}

Circle.prototype = Object.create(Shape.prototype);
Circle.prototype.constructor = Circle;

Circle.prototype.area = function() {
  return Math.PI * this.radius * this.radius;
};

const myCircle = new Circle('Circle', 5);
myCircle.describe(); // This is a Circle
console.log(myCircle.area()); // 78.53981633974483

解析:

  1. Circle 通过 Object.create(Shape.prototype) 继承了 Shape 的方法 describe
  2. Circle 添加了自己的方法 area,实现了继承的同时扩展了新方法。

总结

  • 原型(Prototype) 是对象的一个内部属性,每个对象都有一个与之关联的原型,原型是对象共享方法和属性的机制。
  • 原型链(Prototype Chain) 是多个对象通过原型属性连接起来的链式结构,访问对象属性时会沿着原型链逐级查找。
  • 常见应用场景包括方法共享模拟继承等。

通过理解原型和原型链的机制,我们可以更加高效地管理对象的属性和方法,利用继承和共享减少内存开销,提高代码的复用性和可维护性。


http://www.kler.cn/a/442711.html

相关文章:

  • client-go 的 QPS 和 Burst 限速
  • C#图表性能的巅峰之选:LightningChart®.NET
  • Oracle FLOOR函数的用法
  • C++并发编程之跨应用程序与驱动程序的单生产者单消费者队列
  • Redis优化建议详解
  • 工厂人员定位管理系统方案(二)人员精确定位系统架构设计,适用于工厂智能管理
  • 深度学习中,卷积层的若干思考!!!
  • 【OSS】php使用oss存储
  • 【Elasticsearch】使用阿里云 infererence API 及 semantic text 进行向量搜索
  • 27.多态
  • DuckDB: 两种方法实现动态分组查询
  • 解决git push出现的报错:Permission denied (publickey)
  • 本地项目显示正常,打包部署后ElementUI重点饿图标全部显示异常为小方框
  • 天线覆盖方案简图
  • 云连POS-ERP管理系统ZksrService存在SQL注入漏洞
  • bug之浮点数精度求和计算
  • IntelliJ IDEA中的语言级别版本与目标字节码版本配置
  • c++数据结构算法复习基础--13--基数算法
  • STM32卡死、跑飞、进入HardFault_Handler如何精准的确定问题
  • 【go每日一题】 实现生产者消费者模式
  • 电源的分类
  • windows 使用python共享网络给另外一个网卡
  • 谁说C比C++快?
  • 矩阵的基本知识
  • 【ETCD】ETCD 的一致性读(Linearizable Read)流程解析
  • nexus5x安卓root