JavaScript中原型和原型链详解(举例说明)

JavaScript 的原型和原型链是其继承机制的核心。以下通过具体示例逐步说明:


一、原型(Prototype)

每个 JavaScript 对象都有一个隐藏的 [[Prototype]] 属性(可通过 __proto__Object.getPrototypeOf() 访问),指向它的原型对象。

示例 1:对象的原型
const animal = {
  type: "Unknown",
  sound() {
    console.log("Makes a sound");
  }
};

const dog = {
  breed: "Husky"
};

// 设置 dog 的原型为 animal
Object.setPrototypeOf(dog, animal);

console.log(dog.type); // "Unknown"(来自原型 animal)
dog.sound(); // "Makes a sound"(来自原型 animal)
  • dog 对象本身没有 typesound,但通过原型链访问到了 animal 的属性和方法。

二、构造函数的原型

函数在创建时自动获得一个 prototype 属性,指向一个对象。当用 new 创建实例时,实例的 [[Prototype]] 会指向该对象。

示例 2:构造函数与原型
function Person(name) {
  this.name = name;
}

// 向构造函数的原型添加方法
Person.prototype.sayHello = function() {
  console.log(`Hello, I'm ${this.name}`);
};

const alice = new Person("Alice");
alice.sayHello(); // "Hello, I'm Alice"

console.log(Object.getPrototypeOf(alice) === Person.prototype); // true
  • alicePerson 的实例,它的原型指向 Person.prototype
  • sayHello 方法定义在 Person.prototype 上,所有实例共享它。

三、原型链(Prototype Chain)

当访问对象的属性时,JavaScript 会沿着原型链逐级查找,直到找到属性或到达链的末端(null)。

示例 3:多层原型链
function Animal(name) {
  this.name = name;
}
Animal.prototype.eat = function() {
  console.log(`${this.name} is eating.`);
};

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

// 设置 Dog.prototype 的原型为 Animal.prototype
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog; // 修复构造函数指向

Dog.prototype.bark = function() {
  console.log("Woof!");
};

const myDog = new Dog("Buddy", "Golden Retriever");
myDog.eat(); // "Buddy is eating."(来自 Animal.prototype)
myDog.bark(); // "Woof!"(来自 Dog.prototype)

// 原型链:myDog → Dog.prototype → Animal.prototype → Object.prototype → null
  1. myDog 的原型链
    • myDog 自身有 namebreed
    • myDog.__proto__ 指向 Dog.prototype(包含 bark 方法)。
    • Dog.prototype.__proto__ 指向 Animal.prototype(包含 eat 方法)。
    • Animal.prototype.__proto__ 指向 Object.prototype(包含 toString 等方法)。
    • 最终指向 null,结束查找。

四、关键点总结

  1. 原型

    • 每个对象都有一个原型([[Prototype]])。
    • 构造函数通过 prototype 属性为实例提供共享方法和属性。
  2. 原型链

    • 访问属性时,JavaScript 沿原型链向上查找。
    • 原型链的终点是 Object.prototype.__proto__(即 null)。
  3. 继承实现

    • 通过 Object.create() 或修改 __proto__ 建立原型链。
    • 构造函数中调用父类构造函数(如 Animal.call(this))实现属性继承。

五、验证原型链的工具方法

// 检查对象是否是另一个对象的原型
console.log(Animal.prototype.isPrototypeOf(myDog)); // true

// 查看对象的原型
console.log(Object.getPrototypeOf(myDog)); // Dog.prototype

通过理解原型和原型链,可以更好地掌握 JavaScript 的继承机制和对象设计模式。

你可能感兴趣的:(javascript,原型模式)