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

JavaScript原型和原型链

在JavaScript中,原型(Prototype)和原型链(Prototype Chain)是实现继承和共享属性的关键机制。

原型(Prototype)

每个JavaScript对象都有一个内部属性 [[Prototype]],它指向另一个对象或 null。这个被指向的对象就是原对象的原型。可以通过 Object.getPrototypeOf() 方法来获取一个对象的原型,或者通过对象的 __proto__ 属性(虽然不推荐在生产环境中使用,每个 JavaScript 对象(除了 null)都自动拥有一个隐藏的属性 __proto__,它指向该对象的原型对象。这个 __proto__ 是实现继承的关键)。

原型的主要作用是提供属性和方法的共享。当一个对象试图访问一个属性或方法时,JavaScript引擎首先会在对象自身的属性中查找。如果找不到,它会继续在对象的原型中查找。如果在原型中找到了,可以直接使用。如果没有找到,引擎会继续在原型的原型中查找,直到找到或者到达原型链的顶端(即 null)。

构造函数与原型

在JavaScript中,构造函数(Constructor Function)用于创建对象。当你使用构造函数创建对象时,新对象会自动拥有该构造函数的 prototype 属性作为其原型。这意味着所有通过同一个构造函数创建的对象都可以共享原型上的属性和方法。

例如:

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

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

const alice = new Person('Alice');
alice.sayHello(); // 输出 "Hello, my name is Alice"

在这个例子中,alice 对象没有 sayHello 方法,但它可以调用,因为这个方法是在 Person.prototype 上定义的,而 alice 的原型就是 Person.prototype

原型链(Prototype Chain)

原型链指的是构造函数的 prototype 对象本身也有一个 [[Prototype]] 属性,指向另一个对象,这样就形成了一个链式结构。当在某个对象上查找属性或方法时,会沿着这个链子一直向上查找,直到找到或者到达链的顶端(null)为止。

原型链的顶端通常是 Object.prototype,它是所有对象的最终原型,包含了一些基本的方法和属性,如 toString()valueOf() 等。

示例

假设我们有以下代码:

function Animal() {
    this.type = 'animal';
}

Animal.prototype.speak = function() {
    console.log(this.type + ' makes a noise.');
};

function Dog() {
    this.name = 'dog';
}

Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.speak = function() {
    console.log(this.name + ' barks.');
};

const dog = new Dog();
dog.speak(); // 输出 "dog barks."

在这个例子中,Dog.prototype 是通过 Object.create(Animal.prototype) 创建的,这使得 Dog.prototype 的原型指向 Animal.prototype,从而形成了一条原型链。dog 对象首先在其自身和 Dog.prototype 上查找 speak 方法,找到后就调用 Dog.prototype.speak。如果 Dog.prototype 上没有定义 speak 方法,那么 JavaScript 会继续沿着原型链向上查找,直到找到 speak 方法或者到达链的顶端。

通过原型和原型链,JavaScript 实现了高效的继承机制,使得对象可以共享方法和属性,节省内存空间。

JS 原型的一些好处和坏处:

好处:

  1. 实现继承:原型使得 JS 可以实现基于原型链的继承机制,通过原型链可以实现对象之间的属性和方法的共享和继承。
  2. 节省内存:由于对象的属性和方法都可以通过原型链共享,可以节省内存空间,减少重复创建对象所带来的开销。
  3. 方便扩展:通过原型,可以方便地对对象的属性和方法进行扩展和修改,而不需要修改所有实例对象。
  4. 动态性:原型链是动态的,可以在运行时动态地添加、修改和删除属性和方法,实现灵活性和可变性。

坏处:

  1. 易混淆:原型链概念对于初学者来说可能比较抽象和难以理解,容易混淆和误用。
  2. 性能影响:在原型链中查找属性和方法可能会带来一定的性能开销,特别是在多层原型链中进行查找时。
  3. 难以调试:原型链的查找和继承机制可能会增加代码的复杂性,导致代码难以调试和维护。
  4. 潜在的风险:由于原型链是动态的,可能会导致意外的属性覆盖和修改,造成程序的意外行为。

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

相关文章:

  • 代码随想录二刷|动态规划3
  • 鸿蒙Harmony-应用状态-AppStorage详细介绍
  • 蓝桥杯---排序数组(leetcode第912题)
  • 神经网络常见激活函数 12-Swish函数
  • 游戏引擎学习第104天
  • Nacos 详细介绍:微服务架构中的服务发现与配置管理利器
  • 用大模型学大模型04-机器学习建模过程
  • 基于单片机的常规肺活量SVC简单计算
  • DeepSeek官方推荐的AI集成系统
  • python股票分析系统部署操作过程及代码实现
  • Java 大视界 -- 全球数据治理格局下 Java 大数据的发展路径(89)
  • C++中常用的十大排序方法之3——插入排序
  • C++ 设计模式-组合模式
  • 【vue3】实现pdf在线预览的几种方式
  • 【实战篇】DeepSeek全自动视频工厂搭建指南
  • CAS单点登录(第7版)19.监控和统计
  • 华为OD最新机试真题-投骰子问题-Java-OD统一考试(E卷)
  • DeepSeek 通过 API 对接第三方客户端 告别“服务器繁忙”
  • Typescript 【详解】配置文件 tsconfig.json
  • 【第6章:强化学习基础与深度强化学习—6.4 强化学习在游戏、自动驾驶等领域的应用案例】