JavaScript 使用基于原型的继承模型,这与许多其他语言中基于类的继承不同。理解原型继承是掌握 JavaScript 的关键之一。
每个对象都有一个原型对象:
Object.getPrototypeOf(obj)
或非标准的 obj.__proto__
访问构造函数与原型:
prototype
属性new
关键字调用函数时,新对象的 [[Prototype]]
会指向构造函数的 prototype
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(`${this.name} makes a noise.`);
};
const dog = new Animal('Dog');
dog.speak(); // "Dog makes a noise."
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(`${this.name} makes a noise.`);
};
function Dog(name, breed) {
Animal.call(this, name); // 继承属性
this.breed = breed;
}
// 继承方法
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog; // 修复构造函数指向
Dog.prototype.bark = function() {
console.log(`${this.name} barks!`);
};
const myDog = new Dog('Rex', 'Labrador');
myDog.speak(); // "Rex makes a noise."
myDog.bark(); // "Rex barks!"
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // 调用父类构造函数
this.breed = breed;
}
bark() {
console.log(`${this.name} barks!`);
}
}
const myDog = new Dog('Rex', 'Labrador');
myDog.speak(); // "Rex makes a noise."
myDog.bark(); // "Rex barks!"
Object.create() - 使用指定原型创建新对象
const animal = {
speak() {
console.log(`${this.name} makes a noise.`);
}
};
const dog = Object.create(animal);
dog.name = 'Rex';
dog.speak(); // "Rex makes a noise."
Object.getPrototypeOf() - 获取对象的原型
const proto = Object.getPrototypeOf(dog);
Object.setPrototypeOf() - 设置对象的原型(不推荐,影响性能)
const cat = { name: 'Whiskers' };
Object.setPrototypeOf(cat, animal);
cat.speak(); // "Whiskers makes a noise."
查找机制:当访问对象属性时,JavaScript 会:
null
原型链的顶端:所有原型链最终都指向 Object.prototype
,其原型是 null
性能考虑:过长的原型链会影响查找性能
理解 JavaScript 的原型继承模型对于编写高效、可维护的代码至关重要,尤其是在构建复杂应用程序或框架时。