js原型链的认识

146 阅读2分钟

一、基本介绍

原型(Prototype)

  1. 原型对象:每个 JavaScript 对象都有一个内部属性 [[Prototype]],指向另一个对象,这个对象称为原型对象。可以通过 __proto__ 属性访问这个内部属性(不推荐使用,建议使用 Object.getPrototypeOf)。

  2. 构造函数的 prototype 属性:每个函数(包括构造函数)都有一个 prototype 属性,这个属性指向一个对象,即该函数创建的实例对象的原型对象。

原型链(Prototype Chain)

  1. 原型链的概念:当访问一个对象的属性时,如果该对象没有这个属性,JavaScript 引擎会沿着原型链向上查找,直到找到该属性或到达原型链的顶端(即 null)。

  2. 原型链的顶端:原型链的顶端是 Object.prototype,它的原型是 null

二、关系:实例 & 原型 & 原型对象

1. 浅层关系

image.png

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

// 在构造函数的 prototype 上定义方法
Person.prototype.sayHello = function() {
  console.log('Hello, my name is ' + this.name);
};

// 创建一个实例对象
const alice = new Person('Alice');

// 访问实例对象的方法
alice.sayHello(); // 输出: Hello, my name is Alice

// 验证原型链
console.log(alice.__proto__ === Person.prototype); // 输出: true
console.log(Person.prototype.__proto__ === Object.prototype); // 输出: true
console.log(Object.prototype.__proto__ === null); // 输出: true

2. 深层关系: 原型链的继承

image.png

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

// 在构造函数的 prototype 上定义方法
Animal.prototype.eat = function() {
  console.log(this.name + ' is eating');
};

// 定义另一个构造函数
function Dog(name, breed) {
  Animal.call(this, name); // 调用父类构造函数
  this.breed = breed;
}

// 子类的原型指向父类的实例
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

// 在子类的 prototype 上定义方法
Dog.prototype.bark = function() {
  console.log(this.name + ' is barking');
};

// 创建一个实例对象
const buddy = new Dog('Buddy', 'Golden Retriever');

// 访问实例对象的方法
buddy.eat(); // 输出: Buddy is eating
buddy.bark(); // 输出: Buddy is barking

// 验证原型链
console.log(buddy.__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

总结

  • 原型:每个对象都有一个原型对象,通过 __proto__ 属性或 Object.getPrototypeOf 方法访问。
  • 构造函数的 prototype 属性:指向该构造函数创建的实例对象的原型对象__proto__
  • 原型链:对象通过原型链实现属性和方法的继承,沿着原型链向上查找属性,直到找到或到达原型链的顶端(null)。
  • 继承:通过原型链可以实现对象的继承,子类的原型指向父类的实例(Dog.prototype = Object.create(Animal.prototype);),从而继承父类的方法和属性。