切换语言为:繁体
理解 JavaScript 中的原型和原型链

理解 JavaScript 中的原型和原型链

  • 爱糖宝
  • 2024-06-16
  • 2089
  • 1
  • 0

JavaScript 是一种基于原型的语言,理解原型(prototype)和原型链(prototype chain)对于深入掌握 JavaScript 的面向对象编程非常重要。本文将详细解释什么是原型、原型链以及隐式原型,并通过示例代码来展示它们的工作原理。

原型

在 JavaScript 中,每个函数都有一个 prototype 属性,这个属性是一个对象,包含了由该函数创建的实例对象的公共祖先。当通过构造函数创建一个对象时,实例对象会继承构造函数 prototype 对象上的属性和方法。

// 定义一个构造函数
function Person(name) {
  this.name = name;
}

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

// 通过构造函数创建实例对象
const person1 = new Person('Alice');
const person2 = new Person('Bob');

// 调用实例对象的方法
person1.sayHello(); // 输出:Hello, my name is Alice
person2.sayHello(); // 输出:Hello, my name is Bob

在这个示例中,sayHello 方法被定义在 Person 构造函数的 prototype 上,因此所有通过 Person 构造函数创建的实例对象都可以访问这个方法。

原型链

当我们访问对象的属性或方法时,JavaScript 引擎会先在对象自身查找。如果没有找到,它会沿着原型链向上查找,直到找到属性或方法,或者到达原型链的顶端 null 为止。这个链状的查找过程被称为原型链。

// 定义一个构造函数
function Animal(type) {
  this.type = type;
}

Animal.prototype.eat = function() {
  console.log(`${this.type} is eating`);
};

// 定义另一个构造函数,并将其原型设置为 Animal 的实例
function Dog(name) {
  Animal.call(this, 'Dog');
  this.name = name;
}

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

Dog.prototype.bark = function() {
  console.log(`${this.name} is barking`);
};

// 创建 Dog 的实例
const dog = new Dog('Buddy');

// 调用实例对象的方法
dog.eat(); // 输出:Dog is eating
dog.bark(); // 输出:Buddy is barking

在这个示例中,Dog 的原型被设置为 Animal 的实例,因此 Dog 的实例对象可以访问 Animal 原型上的 eat 方法。这个查找过程就是原型链的实际应用。

  理解 JavaScript 中的原型和原型链

将代码放到浏览器我们可以通过控制台我们可以查看它的原型查找过程,直到找到object的隐式原型为空原型链的查找就到头了

隐式原型

每个 JavaScript 对象都有一个 __proto__ 属性,这个属性指向创建该对象的构造函数的 prototype。通过 __proto__ 属性,可以实现原型链的查找。

// 检查 dog 对象的隐式原型
console.log(dog.__proto__ === Dog.prototype); // 输出:true
console.log(Dog.prototype.__proto__ === Animal.prototype); // 输出:true
console.log(Animal.prototype.__proto__ === Object.prototype); // 输出:true
console.log(Object.prototype.__proto__ === null); // 输出:true

在这个示例中,我们可以看到 dog 对象的 __proto__ 属性指向 Dog 构造函数的 prototype,而 Dog.prototype.__proto__ 指向 Animal.prototype,最终 Animal.prototype.__proto__ 指向 Object.prototypeObject.prototype.__proto__null,表示原型链的终点。

所有对象都有原型吗?

并不是所有的对象都有原型。通过 Object.create(null) 创建的对象没有原型。

// 创建一个没有原型的对象
const obj = Object.create(null);

console.log(obj.__proto__); // 输出:undefined
console.log(Object.getPrototypeOf(obj)); // 输出:null

在这个示例中,我们创建了一个没有原型的对象 obj,因此 obj.__proto__undefinedObject.getPrototypeOf(obj) 返回 null

结论

通过理解原型、原型链和隐式原型,我们可以更好地掌握 JavaScript 的面向对象编程。这些概念帮助我们理解对象之间的继承关系,以及如何通过原型链实现方法和属性的共享。希望这篇文章和示例代码能帮助你更深入地理解 JavaScript 中的原型机制。

最后:

理解 JavaScript 中的原型和原型链 

大家可以通过分析一下这张图来加深印象

0条评论

您的电子邮件等信息不会被公开,以下所有项均必填

OK! You can skip this field.