什么是原型链?
在JavaScript中,原型链是实现对象继承的主要方式。每个对象都有一个内部链接指向另一个对象,称为它的原型(prototype)。这个原型对象也有自己的原型,这样就形成了一个链式结构,我们称之为原型链。
原型链的基本概念
1. 对象原型
每个JavaScript对象都有一个特殊的内部属性 [[Prototype]]
(在浏览器中通常用 __proto__
访问)。
const person = {
name: '张三'
};
console.log(person.__proto__ === Object.prototype); // true
2. 构造函数和原型对象
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log(`你好,我是${this.name}`);
}
const person1 = new Person('李四');
person1.sayHello(); // 输出:你好,我是李四
原型链继承示例
让我们看一个完整的继承示例:
// 父类
function Animal(name) {
this.name = name;
}
Animal.prototype.eat = function() {
console.log(`${this.name}正在吃东西`);
}
// 子类
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('汪汪汪!');
}
const myDog = new Dog('小黑', '柴犬');
myDog.eat(); // 输出:小黑正在吃东西
myDog.bark(); // 输出:汪汪汪!
原型链的查找机制
- 当访问一个对象的属性时,JavaScript首先在对象自身查找该属性
- 如果没找到,就会继续在该对象的原型对象中查找
- 如果还没找到,就会继续在原型的原型中查找
- 这个过程会一直持续到找到该属性或到达原型链的末端(null)
常见陷阱和注意事项
- 属性遮蔽:如果对象自身和原型链上有同名属性,对象自身的属性会"遮蔽"原型链上的属性
function Person() {}
Person.prototype.name = '默认名字';
const person = new Person();
console.log(person.name); // 输出:默认名字
person.name = '张三';
console.log(person.name); // 输出:张三
- 原型污染:修改原型对象可能影响所有继承该原型的对象
最佳实践
- 使用
Object.create()
创建对象之间的继承关系 - 避免直接修改
Object.prototype
- 优先使用类(Class)语法来创建继承关系
- 使用
Object.getPrototypeOf()
替代__proto__
总结
原型链是JavaScript中实现继承的核心机制,理解原型链对于掌握JavaScript面向对象编程至关重要。通过合理使用原型链,我们可以实现代码复用和继承关系的建立。