JavaScript prototype(原型对象)
                           
天天向上
发布: 2025-02-28 23:56:28

原创
289 人浏览过

学习 JavaScript prototype(原型对象) 是非常重要的一部分,它帮助你理解 JavaScript 中对象和继承的机制。原型是每个 JavaScript 对象的隐式属性,它指向一个对象,这个对象包含了该对象的共享属性和方法。

1. 原型链与继承机制

原型链

每个对象都有一个 __proto__ 属性,指向它的原型对象。原型对象本身也有自己的 __proto__,直到最终指向 Object.prototype,这是原型链的最顶层。

例如,创建一个对象并检查它的原型链:

const obj = { name: "Alice" };

console.log(obj.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__ === null); // true
  • obj__proto__ 指向 Object.prototype
  • Object.prototype.__proto__null,表示原型链的终点。

原型链的继承

通过原型链,子对象可以继承父对象的属性和方法。来看一个例子:

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

Animal.prototype.speak = function() {
  console.log(this.name + " makes a sound.");
};

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

Dog.prototype = Object.create(Animal.prototype);  // 继承Animal的方法
Dog.prototype.constructor = Dog;  // 修正构造函数指向

const dog = new Dog('Buddy');
dog.speak();  // 输出:Buddy makes a sound.

解释

  • Dog.prototype = Object.create(Animal.prototype) 使得 Dog 的实例能够访问 Animal 中的方法。
  • Dog.prototype.constructor = Dog 用来修正 Dog 构造函数的指向,因为继承时会修改 constructor

2. Prototype 属性与实例化

prototype 属性

每个函数(构造函数)都有一个 prototype 属性,它指向一个对象,这个对象包含该构造函数实例的共享方法。

例如:

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

Person.prototype.sayHello = function() {
  console.log("Hello, " + this.name);
};

const person1 = new Person("Alice");
const person2 = new Person("Bob");

person1.sayHello();  // Hello, Alice
person2.sayHello();  // Hello, Bob

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

解释

  • Person.prototype 存储的是 sayHello 方法,它是所有 Person 实例共享的。
  • person1.__proto__person2.__proto__ 都指向 Person.prototype

创建实例时如何访问原型

function Car(make, model) {
  this.make = make;
  this.model = model;
}

Car.prototype.drive = function() {
  console.log(this.make + " " + this.model + " is driving.");
};

const car1 = new Car("Toyota", "Corolla");
const car2 = new Car("Honda", "Civic");

car1.drive();  // Toyota Corolla is driving.
car2.drive();  // Honda Civic is driving.

重点

  • drive 方法是通过 Car.prototype 来共享的。
  • 每个实例有自己的属性(make, model),但是它们共享 drive 方法。

3. 原型方法和继承

通过原型添加方法

我们可以通过原型为所有实例添加方法。例如,为 Person 类添加一个 introduce 方法:

Person.prototype.introduce = function() {
  console.log("Hi, I'm " + this.name);
};

const person3 = new Person("Charlie");
person3.introduce();  // Hi, I'm Charlie

原型链的优势

  • 所有 Person 类的实例都可以访问 introduce 方法,而不需要每个实例都拥有一个副本。

继承父类原型方法

我们可以通过 Object.create 继承父类的原型方法:

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

Animal.prototype.speak = function() {
  console.log(this.name + " makes a sound.");
};

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

Cat.prototype = Object.create(Animal.prototype);  // 继承父类原型方法
Cat.prototype.constructor = Cat;  // 修正构造函数

const cat1 = new Cat("Whiskers");
cat1.speak();  // Whiskers makes a sound.

解释

  • Object.create(Animal.prototype) 创建一个新的对象作为 Cat.prototype,它继承了 Animal.prototype 上的方法。
  • Cat.prototype.constructor = Cat 用于确保 Cat 实例的构造函数是 Cat

4. 修改原型链

你可以修改对象的原型链,给对象动态添加方法或属性:

const person4 = new Person("David");

person4.__proto__.sayGoodbye = function() {
  console.log(this.name + " says goodbye.");
};

person4.sayGoodbye();  // David says goodbye.

注意

  • 这种修改会影响所有继承该原型链的实例。

5. 实践案例:创建一个动物类和子类

让我们创建一个动物类,并添加不同类型的动物:

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

Animal.prototype.speak = function() {
  console.log(this.name + " makes a sound.");
};

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

Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.bark = function() {
  console.log(this.name + " barks.");
};

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

Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.constructor = Cat;

Cat.prototype.meow = function() {
  console.log(this.name + " meows.");
};

// 创建实例
const dog = new Dog("Buddy");
const cat = new Cat("Whiskers");

dog.speak();  // Buddy makes a sound.
dog.bark();   // Buddy barks.

cat.speak();  // Whiskers makes a sound.
cat.meow();   // Whiskers meows.

总结

  • DogCat 继承了 Animalspeak 方法,但各自有自己独特的方法(barkmeow)。
  • 这种方式实现了简单的继承关系。

更多详细内容请关注其他文章!

发表回复 0

Your email address will not be published. Required fields are marked *