FPF   付鹏篚的笔记
  • 主页
  • 归档
  • 分类
  • 标签
  • 关于

付鹏篚

  • 主页
  • 归档
  • 分类
  • 标签
  • 关于
Quiet主题
  • JavaScript

原型链

付鹏篚
JavaScript

2020-12-11 20:00:00

文章目录
  1. 一、什么是原型链?
  2. 二、原型链的基本原理
  3. 三、原型链的构建
  4. 四、原型链的例子
    1. 1. 基本示例:构造函数与原型链
    2. 2. 多级原型链
    3. 3. 原型链的继承与 constructor
  5. 五、原型链的特点
  6. 六、__proto__ 和 prototype 的区别
    1. 示例:
  7. 七、总结

image-20250228165638690

一、什么是原型链?

在 JavaScript 中,每个对象都有一个内部属性 [[Prototype]],指向另一个对象,这个指向的对象被称为原型(prototype)。通过原型,子对象可以访问父对象的属性和方法。原型链就是一系列对象通过 prototype 属性连接起来的链条,最终指向 null。

二、原型链的基本原理

  • 每个 JavaScript 对象都有一个 prototype 属性,指向其原型对象。
  • 当访问一个对象的属性时,JavaScript 引擎会先查找对象本身,如果找不到,则会顺着 [[Prototype]] 链向上查找,直到找到该属性或者到达链条的末端 null。
  • 如果原型链中的每个对象都没有找到该属性或方法,最终返回 undefined。

三、原型链的构建

  1. 对象的原型:
    • 对于由构造函数创建的对象(如 new Object()、new Array() 等),它们的原型对象是该构造函数的 prototype 属性。
    • Object 的原型是 null,即原型链的终点。
  2. 构造函数的 prototype 属性:
    • 每个构造函数都有一个 prototype 属性,这个属性是一个对象,包含了该构造函数创建的实例的默认属性和方法(如 constructor 属性)。

四、原型链的例子

1. 基本示例:构造函数与原型链

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

Animal.prototype.sayHello = function() {
  console.log(`${this.name} says hello!`);
};

const dog = new Animal('Buddy');
dog.sayHello();  // 输出 "Buddy says hello!"

console.log(dog.__proto__ === Animal.prototype);  // true
  • dog 是 Animal 构造函数的一个实例。
  • dog 对象没有 sayHello 方法,但是它的原型 dog.__proto__ 指向 Animal.prototype,所以 dog 可以访问 Animal.prototype 中的方法。
  • dog.__proto__ === Animal.prototype 返回 true,证明 dog 的原型链确实指向了 Animal.prototype。

2. 多级原型链

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

Animal.prototype.sayHello = function() {
  console.log(`${this.name} says hello!`);
};

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

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

const myDog = new Dog('Buddy', 'Golden Retriever');
myDog.sayHello();  // 输出 "Buddy says hello!"
console.log(myDog instanceof Dog);  // true
console.log(myDog instanceof Animal);  // true
  • Dog 通过 Object.create(Animal.prototype) 设置了自己的原型链指向 Animal.prototype,从而继承了 Animal 的方法。
  • myDog 可以访问 Animal.prototype 中的方法,并且 myDog instanceof Dog 和 myDog instanceof Animal 都返回 true,说明 myDog 既是 Dog 的实例,也是 Animal 的实例。

3. 原型链的继承与 constructor

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

function Dog(name, breed) {
  Animal.call(this, name);
  this.breed = breed;
}

Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;  // 修复 constructor 指向

const myDog = new Dog('Buddy', 'Golden Retriever');
console.log(myDog.constructor);  // Dog() 构造函数
  • 在上面的代码中,Dog.prototype.constructor 被设置为 Dog,以修复继承链中的 constructor 指向,使得 myDog.constructor 返回的是 Dog 构造函数。

五、原型链的特点

  1. 共享属性和方法:
    • 原型链的最大特点是,多个实例可以共享原型对象上的方法和属性,而不需要每次创建实例时都重新定义。
  2. 性能问题:
    • 访问原型链上的属性时,性能相对较低,因为 JavaScript 需要逐层查找原型链,直到找到属性或者原型链的末尾。
    • 如果有大量的原型链查找,可能会影响性能,因此应尽量避免在原型链上放置频繁访问的属性。
  3. 原型链的终点是 null:
    • 所有对象的原型链最终都会指向 null,这标志着原型链的结束。

六、__proto__ 和 prototype 的区别

  • prototype 是构造函数上的属性,用来为该构造函数创建的对象实例提供原型对象。
  • __proto__ 是对象上的属性,指向该对象的原型对象,即该对象的构造函数的 prototype 属性。

示例:

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

const dog = new Animal('Buddy');

console.log(dog.__proto__ === Animal.prototype);  // true
console.log(Animal.prototype.__proto__ === Object.prototype);  // true

七、总结

  • 原型链 是对象和构造函数之间的一个连接机制,它使得对象能够继承构造函数的属性和方法。
  • 每个对象都通过 [[Prototype]] 指向其构造函数的 prototype 属性,而构造函数的 prototype 属性指向其父类的原型对象,最终形成一个链条,链条的尽头是 null。
  • 通过原型链,JavaScript 实现了继承的机制,允许对象共享属性和方法。
上一篇

闭包 (Closure)

下一篇

插槽的使用

©2025 By 付鹏篚. 主题:Quiet
Quiet主题