原型与原型链
约 653 字大约 2 分钟
2025-02-03
问题
原型与原型链是什么?
在 JavaScript 中,原型(Prototype) 和 原型链(Prototype Chain) 是实现继承的核心机制。理解它们对于掌握 JavaScript 的面向对象编程至关重要。
1. 原型(Prototype)
每个 JavaScript 对象(除了 null
)都有一个内部属性 [[Prototype]]
,指向它的原型对象。原型对象也是一个普通对象,它包含可以被其他对象共享的属性和方法。
- 在 ES5 中,可以通过
Object.getPrototypeOf(obj)
获取对象的原型。 - 在 ES6 中,可以通过
obj.__proto__
直接访问对象的原型(不推荐在生产环境中使用)。
示例:
const person = {
name: "Alice",
greet() {
console.log(`Hello, my name is ${this.name}`);
}
};
const student = Object.create(person); // student 的原型是 person
student.name = "Bob";
student.greet(); // 输出: Hello, my name is Bob
在上面的例子中,student
对象继承了 person
对象的 greet
方法。
2. 原型链(Prototype Chain)
当访问一个对象的属性或方法时,JavaScript 引擎会按照以下顺序查找:
- 对象本身是否有该属性或方法。
- 如果没有,则查找对象的原型(
[[Prototype]]
)。 - 如果原型上也没有,则继续查找原型的原型,直到找到或到达原型链的顶端(
null
)。
这种链式查找的机制就是 原型链。
示例:
const animal = {
type: "Animal",
describe() {
console.log(`I am a ${this.type}`);
}
};
const dog = Object.create(animal);
dog.type = "Dog";
const puppy = Object.create(dog);
puppy.type = "Puppy";
puppy.describe(); // 输出: I am a Puppy
查找过程:
puppy
本身没有describe
方法。- 查找
puppy
的原型dog
,dog
也没有describe
方法。 - 继续查找
dog
的原型animal
,animal
有describe
方法,调用它。
3. 构造函数与原型
在 JavaScript 中,函数也是对象,每个函数都有一个 prototype
属性(注意:不是 [[Prototype]]
)。当使用 new
关键字调用构造函数时,创建的对象会将其 [[Prototype]]
指向构造函数的 prototype
属性。
示例:
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
console.log(`Hello, my name is ${this.name}`);
};
const alice = new Person("Alice");
alice.greet(); // 输出: Hello, my name is Alice
Person.prototype
是alice
对象的原型。alice.__proto__ === Person.prototype
为true
。
4. 原型链的顶端
所有对象的原型链最终都会指向 Object.prototype
,而 Object.prototype
的原型是 null
。
console.log(Object.prototype.__proto__); // 输出: null
5. 总结
- 原型:每个对象都有一个原型对象,用于共享属性和方法。
- 原型链:通过原型链,对象可以访问其原型链上的属性和方法。
- 构造函数:通过构造函数的
prototype
属性,可以为实例对象提供共享的属性和方法。 - 继承:原型链是实现 JavaScript 继承的基础。