谈谈js原型链

米阳 2022-11-24 182 11/24

JavaScript 的原型链是其实现继承和属性共享的核心机制,理解原型链需要从对象、构造函数、原型对象之间的关系入手。

首先要认清几个基本概念

  • 对象(Object)​:就是具体的数据,比如 { name: "小明" }
  • 构造函数(Constructor)​: 用来创建对象的“模板函数”,比如 function Person() {}
  • 原型对象(Prototype)​:一个特殊的对象,用来存放共享的属性和方法,比如 Person.prototype

核心原理:原型链如何工作

1. 原型链的本质:对象之间的“继承链”​

  • 每个对象都有一个隐藏属性 [[Prototype]](可以通过 __proto__ 或 Object.getPrototypeOf() 访问),指向它的“原型对象”。
  • 原型对象本身也是对象,它也有自己的 [[Prototype]],这样层层链接,直到最终指向 null,形成一条链。
  • // 创建一个对象
    const obj = { name: "小明" };
    
    // 原型链:obj → Object.prototype → null
    console.log(obj.__proto__ === Object.prototype); // true
    console.log(Object.prototype.__proto__); // null

2. 构造函数和原型的关系

  • 构造函数有一个 prototype 属性,指向它的原型对象。
  • 实例对象通过 new 调用构造函数创建,其 __proto__ 指向构造函数的 prototype
  • function Person(name) {
      this.name = name;
    }
    
    // 实例对象
    const person1 = new Person("小明");
    
    // 原型链关系
    console.log(person1.__proto__ === Person.prototype); // true
    console.log(Person.prototype.__proto__ === Object.prototype); // true

     

3. 属性查找机制:逐级向上找

当访问对象的属性时:

  1. 先找自己:对象自身是否有这个属性?
  2. 找不到就向上找原型:沿着 __proto__ 链一层层向上查找。
  3. 直到终点:如果找到 null 还没找到,返回 undefined
function Person() {}
Person.prototype.sayHello = function() {
  console.log("Hello!");
};

const person1 = new Person();
person1.sayHello(); // 调用的是原型上的方法!
console.log(person1.toString()); // 来自 Object.prototype

 

实际应用:为什么原型链重要?

实现方法共享(省内存)​

  • 所有实例共享原型上的方法,而不是每个实例单独创建。
function Dog(name) {
  this.name = name;
}
// 方法放在原型上
Dog.prototype.bark = function() {
  console.log("汪汪!");
};

const dog1 = new Dog("小黑");
const dog2 = new Dog("小白");
dog1.bark(); // 共享同一个 bark 方法

实现继承

  • 子类继承父类:通过让子类的原型指向父类的实例。
  • 经典继承示例
    // 父类
    function Animal() {
      this.type = "动物";
    }
    Animal.prototype.eat = function() {
      console.log("吃东西");
    };
    
    // 子类
    function Dog() {
      Animal.call(this); // 调用父类构造函数,继承属性
    }
    Dog.prototype = Object.create(Animal.prototype); // 继承方法
    Dog.prototype.constructor = Dog; // 修正 constructor 指向
    
    const dog = new Dog();
    dog.eat(); // "吃东西"(来自父类原型)
    console.log(dog.type); // "动物"(来自父类构造函数)

     

修改内置对象

  • 可以通过修改原型,给所有内置对象(如数组、字符串)添加方法。
    // 给所有数组添加一个求和方法
    Array.prototype.sum = function() {
      return this.reduce((total, num) => total + num, 0);
    };
    const arr = [1, 2, 3];
    console.log(arr.sum()); // 6

     

 

 

- THE END -

米阳

3月24日10:08

最后修改:2025年3月24日
0

非特殊说明,本博所有文章均为博主原创。

共有 0 条评论