1. 原型链基础概念
原型(Prototype) 是 JavaScript 中实现继承和属性共享的核心机制。每个对象都有一个内部链接指向另一个对象,这个链接就是原型链。
1.1 原型链结构
对象 → 原型 → 原型 → ... → null
2. 原型相关属性
2.1 核心属性
| 属性 | 类型 | 说明 | 示例 |
|---|---|---|---|
| prototype | 静态属性 | 仅函数对象拥有,用于定义该函数创建的对象实例的默认原型 | function Foo() {}; Foo.prototype |
| proto | 实例属性 | 对象实例的原型指针(已弃用,但广泛支持) | obj.__proto__ |
| constructor | 实例属性 | 创建该对象的构造函数 | obj.constructor |
2.2 原型链访问方法
| 方法 | 说明 | 示例 |
|---|---|---|
| Object.getPrototypeOf() | 获取对象的原型(推荐使用) | Object.getPrototypeOf(obj) |
| Object.setPrototypeOf() | 设置对象的原型 | Object.setPrototypeOf(obj, proto) |
| Object.create() | 创建新对象并指定原型 | Object.create(proto) |
3. 详细说明
3.1 prototype 属性
仅函数对象拥有 prototype 属性,用于定义通过该函数创建的对象实例的默认原型。
javascript
function Person(name) {
this.name = name;
}
// 在 prototype 上添加方法
Person.prototype.sayHello = function() {
return `Hello, I'm ${this.name}`;
};
const john = new Person('John');
console.log(john.sayHello()); // "Hello, I'm John"
console.log(john.__proto__ === Person.prototype); // true
3.2 proto 属性
每个对象实例都有 proto 属性,指向其原型对象。
javascript
const obj = {};
console.log(obj.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__); // null
⚠️ 注意 :__proto__ 是历史遗留属性,虽然被广泛支持,但不是标准属性 。ES6 推荐使用 Object.getPrototypeOf() 替代。
3.3 constructor 属性
指向创建该对象的构造函数。
javascript
function Animal() {}
const dog = new Animal();
console.log(dog.constructor === Animal); // true
console.log(dog.constructor === Object); // false
4. 原型链继承示例
javascript
// 基类
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
return `${this.name} makes a sound`;
};
// 子类
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() {
return `${this.name} barks!`;
};
const myDog = new Dog('Buddy', 'Golden Retriever');
console.log(myDog.speak()); // "Buddy makes a sound"
console.log(myDog.bark()); // "Buddy barks!"
console.log(myDog instanceof Animal); // true
console.log(myDog instanceof Dog); // true
5. 现代 ES6+ 替代方案
5.1 class 语法糖
javascript
class Animal {
constructor(name) {
this.name = name;
}
speak() {
return `${this.name} makes a sound`;
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name);
this.breed = breed;
}
bark() {
return `${this.name} barks!`;
}
}
5.2 使用 Object.create()
javascript
const animal = {
speak() {
return `${this.name} makes a sound`;
}
};
const dog = Object.create(animal);
dog.name = 'Buddy';
dog.bark = function() {
return `${this.name} barks!`;
};
6. 原型链查找机制
当访问对象的属性时,JavaScript 会按以下顺序查找:
- 检查对象自身是否有该属性
- 如果没有,检查原型链上的原型对象
- 继续向上查找,直到找到属性或到达原型链末端(null)
javascript
const obj = {};
obj.__proto__ = { sharedProp: 'I am shared' };
console.log(obj.sharedProp); // "I am shared" - 从原型链找到
console.log(obj.hasOwnProperty('sharedProp')); // false - 不是自身属性
7. 注意事项
- 不要直接修改内置对象的原型 (如
Object.prototype、Array.prototype),这会影响所有对象 - 使用
Object.create(null)创建无原型的对象,避免继承 Object.prototype 上的方法 - 原型链过长会影响性能,尽量保持简洁
- 使用
instanceof检查类型,它会沿着原型链查找
8. 总结
| 概念 | 说明 | 推荐用法 |
|---|---|---|
| prototype | 函数的原型属性 | 用于定义构造函数创建的对象共享的方法 |
| proto | 对象的原型指针 | 避免使用,用 Object.getPrototypeOf() 替代 |
| 原型链 | 对象之间的继承关系 | 理解继承机制的核心 |
| constructor | 构造函数引用 | 可用于类型检查或创建新实例 |
最佳实践 :在现代 JavaScript 开发中,优先使用 ES6 的 class 语法,它提供了更清晰的原型继承语法,同时底层仍然基于原型链实现。