优化后的代码示例
// 定义 Animal 构造函数
function Animal(name) {
this.name = name;
}
// 给 Animal 的原型添加方法
Animal.prototype.speak = function() {
console.log(this.name +'makes a sound.');
};
// 定义 Dog 构造函数
function Dog(name, breed) {
// 调用 Animal 的构造函数,将 this 上下文传递过去,以初始化 name 属性
Animal.call(this, name);
this.breed = breed;
}
// 设置 Dog 的原型为 Animal 的实例,从而实现继承
Dog.prototype = Object.create(Animal.prototype);
// 修正 Dog 原型的 constructor 属性,使其指向 Dog 构造函数
Dog.prototype.constructor = Dog;
// 给 Dog 的原型添加方法
Dog.prototype.bark = function() {
console.log(this.name +'barks.');
};
原型链在其中的作用
- 实现继承:通过
Dog.prototype = Object.create(Animal.prototype)
,将 Dog
的原型设置为 Animal
原型的一个实例。这意味着 Dog
实例可以访问 Animal
原型上定义的方法,如 speak
方法。当在 Dog
实例上调用 speak
方法时,JavaScript 引擎会沿着原型链查找,从 Dog
实例的自有属性开始,找不到则查找 Dog
的原型(即 Animal
原型的实例),如果还找不到,继续沿着 Animal
原型向上查找,直到找到该方法或者到达原型链的顶端(null
)。
- 节省内存:将公共的属性和方法定义在原型上,而不是每个实例都重新创建一份。例如,
speak
方法定义在 Animal
的原型上,所有 Animal
的实例(包括 Dog
实例,因为 Dog
继承自 Animal
)都可以共享这个方法,而不是每个实例都有自己独立的 speak
方法副本,从而节省了内存空间。
- 增强代码的可维护性和扩展性:如果需要对
Animal
的某个方法进行修改或添加新的方法,只需要在 Animal
的原型上进行操作,所有继承自 Animal
的构造函数(如 Dog
)的实例都会受到影响,不需要在每个实例或者每个构造函数内部重复修改代码。