一、基本介绍
原型(Prototype)
-
原型对象:每个 JavaScript 对象都有一个内部属性
[[Prototype]],指向另一个对象,这个对象称为原型对象。可以通过__proto__属性访问这个内部属性(不推荐使用,建议使用Object.getPrototypeOf)。 -
构造函数的
prototype属性:每个函数(包括构造函数)都有一个prototype属性,这个属性指向一个对象,即该函数创建的实例对象的原型对象。
原型链(Prototype Chain)
-
原型链的概念:当访问一个对象的属性时,如果该对象没有这个属性,JavaScript 引擎会沿着原型链向上查找,直到找到该属性或到达原型链的顶端(即
null)。 -
原型链的顶端:原型链的顶端是
Object.prototype,它的原型是null。
二、关系:实例 & 原型 & 原型对象
1. 浅层关系
// 定义一个构造函数
function Person(name) {
this.name = name;
}
// 在构造函数的 prototype 上定义方法
Person.prototype.sayHello = function() {
console.log('Hello, my name is ' + this.name);
};
// 创建一个实例对象
const alice = new Person('Alice');
// 访问实例对象的方法
alice.sayHello(); // 输出: Hello, my name is Alice
// 验证原型链
console.log(alice.__proto__ === Person.prototype); // 输出: true
console.log(Person.prototype.__proto__ === Object.prototype); // 输出: true
console.log(Object.prototype.__proto__ === null); // 输出: true
2. 深层关系: 原型链的继承
// 定义一个构造函数
function Animal(name) {
this.name = name;
}
// 在构造函数的 prototype 上定义方法
Animal.prototype.eat = function() {
console.log(this.name + ' is eating');
};
// 定义另一个构造函数
function Dog(name, breed) {
Animal.call(this, name); // 调用父类构造函数
this.breed = breed;
}
// 子类的原型指向父类的实例
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
// 在子类的 prototype 上定义方法
Dog.prototype.bark = function() {
console.log(this.name + ' is barking');
};
// 创建一个实例对象
const buddy = new Dog('Buddy', 'Golden Retriever');
// 访问实例对象的方法
buddy.eat(); // 输出: Buddy is eating
buddy.bark(); // 输出: Buddy is barking
// 验证原型链
console.log(buddy.__proto__ === Dog.prototype); // 输出: true
console.log(Dog.prototype.__proto__ === Animal.prototype); // 输出: true
console.log(Animal.prototype.__proto__ === Object.prototype); // 输出: true
console.log(Object.prototype.__proto__ === null); // 输出: true
总结
- 原型:每个对象都有一个原型对象,通过
__proto__属性或Object.getPrototypeOf方法访问。 - 构造函数的
prototype属性:指向该构造函数创建的实例对象的原型对象__proto__。 - 原型链:对象通过原型链实现
属性和方法的继承,沿着原型链向上查找属性,直到找到或到达原型链的顶端(null)。 - 继承:通过原型链可以实现对象的继承,
子类的原型指向父类的实例(Dog.prototype = Object.create(Animal.prototype);),从而继承父类的方法和属性。