原型链 - DeepSeek

在 JavaScript 中,原型链(Prototype Chain)是实现继承的核心机制。理解原型链需要掌握以下几个关键概念:

原型(Prototype)

每个 JavaScript 对象(除 null 外)都有一个内部属性 [[Prototype]],指向它的原型对象。原型对象也是一个普通对象,它包含共享的属性和方法。

  • 通过 Object.getPrototypeOf(obj)obj.proto 可以访问对象的原型。

  • 通过 Object.setPrototypeOf(obj, prototype)obj.proto = prototype 可以设置对象的原型。

构造函数(Constructor)

构造函数是用来创建对象的函数。通过 new 关键字调用构造函数时,会创建一个新对象,并将该对象的原型指向构造函数的 prototype 属性。

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

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

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

prototype 属性

每个函数都有一个 prototype 属性,它是一个对象。当使用 new 关键字创建实例时,实例的 [[Prototype]] 会指向该函数的 prototype 对象。

console.log(person.__proto__ === Person.prototype); // true

原型链(Prototype Chain)

当访问一个对象的属性或方法时,JavaScript 引擎会先在对象自身查找,如果找不到,则会沿着原型链向上查找,直到找到该属性或方法,或者到达原型链的顶端(null)。

console.log(person.toString()); // 输出: [object Object]
  • person 对象本身没有 toString 方法。

  • JavaScript 引擎会沿着原型链查找,最终在 Object.prototype 上找到 toString 方法。

Object.prototype

Object.prototype 是所有对象的原型链的顶端。它的原型是 null

console.log(Object.getPrototypeOf(Object.prototype)); // null

继承

通过原型链,JavaScript 可以实现继承。子类的原型可以指向父类的实例,从而继承父类的属性和方法。

function Student(name, grade) {
    Person.call(this, name); // 调用父类构造函数
    this.grade = grade;
}

// 设置 Student 的原型为 Person 的实例
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;

const student = new Student('Bob', 10);
student.sayHello(); // 输出: Hello, my name is Bob

instanceofisPrototypeOf

  • instanceof 用于检查对象是否是某个构造函数的实例。

  • isPrototypeOf 用于检查某个对象是否在另一个对象的原型链上。

console.log(student instanceof Person); // true
console.log(Person.prototype.isPrototypeOf(student)); // true

总结

  • 原型链是 JavaScript 实现继承的基础。

  • 每个对象都有一个原型,通过 [[Prototype]]proto 访问。

  • 构造函数的 prototype 属性指向原型对象。

  • 原型链的顶端是 Object.prototype,其原型为 null

  • 通过原型链,对象可以继承其他对象的属性和方法。

理解原型链有助于更好地掌握 JavaScript 的面向对象编程和继承机制。

案例 - 浏览器环境navigator分析

思考:navigator对象的原型对象是谁?

  • navigator.__proto__ === Navigator(原型)

  • navigator.__proto__ === Navigator.prototype(原型对象)

Last updated