原型链概念
在 JavaScript 中,原型链(prototype chain)是实现继承和共享属性机制的一种方法。每个对象都有一个内部链接指向另一个对象,这个链接称为原型。这个原型对象也有自己的原型,形成一条原型链,最终指向 null
。
原型链的基础
-
构造函数和原型对象:
- 每个函数都有一个
prototype
属性,它指向一个对象,这个对象包含了由该构造函数创建的实例共享的属性和方法。
- 每个函数都有一个
-
实例对象的
__proto__
:- 每个对象都有一个
__proto__
属性(在规范中称为[[Prototype]]
),它指向构造函数的prototype
对象。
- 每个对象都有一个
原型链示例
让我们通过一个具体的例子来理解原型链:
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log(`Hello, my name is ${this.name}`);
};
const person1 = new Person('Alice');
person1.sayHello(); // 输出:Hello, my name is Alice
console.log(person1.__proto__ === Person.prototype); // 输出:true
console.log(Person.prototype.__proto__ === Object.prototype); // 输出:true
console.log(Object.prototype.__proto__ === null); // 输出:true
原型链的工作原理
-
创建实例对象:
- 当我们使用
new Person('Alice')
创建person1
时,person1
对象的__proto__
属性指向Person.prototype
。
- 当我们使用
-
访问属性和方法:
- 当访问
person1.sayHello
时,JavaScript 引擎首先检查person1
对象本身是否有这个属性或方法。 - 如果没有,它会沿着原型链向上查找,即检查
person1.__proto__
,即Person.prototype
。 - 如果在
Person.prototype
找到这个方法,就会调用它。
- 当访问
-
继续向上查找:
- 如果在
Person.prototype
上也找不到,查找会继续向上,检查Person.prototype.__proto__
,即Object.prototype
。 - 如果最终在
Object.prototype
上也找不到,查找会停止,返回undefined
。
- 如果在
原型链结构图
person1 (实例对象)
|
|.__proto__
v
Person.prototype (构造函数的原型对象)
|
|.__proto__
v
Object.prototype (根原型对象)
|
|.__proto__
v
null
原型链与继承
通过原型链,JavaScript 实现了继承机制,让对象能够共享属性和方法。例如:
function Animal(name) {
this.name = name;
}
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;
Dog.prototype.bark = function() {
console.log(`${this.name} is barking`);
};
const dog1 = new Dog('Buddy', 'Golden Retriever');
dog1.eat(); // 输出:Buddy is eating
dog1.bark(); // 输出:Buddy is barking
详细解释
-
构造函数:
Animal
和Dog
都是构造函数。Dog
的构造函数中调用了Animal.call(this, name)
,以确保Dog
的实例能够继承Animal
构造函数中的属性。
-
继承原型:
Dog.prototype = Object.create(Animal.prototype)
创建了一个新的对象,这个对象的原型是Animal.prototype
。- 这样,
Dog
的实例会继承Animal
原型中的方法。
-
修正
constructor
:Dog.prototype.constructor = Dog
确保Dog
原型对象的constructor
属性正确指向Dog
构造函数。
-
实例化和方法调用:
- 创建
dog1
实例后,它可以调用Animal.prototype
中的方法(如eat
)和Dog.prototype
中的方法(如bark
)。
- 创建
总结
- 原型链:每个对象都有一个指向原型对象的内部链接,通过这个链接形成的链条称为原型链。
- 继承机制:原型链是 JavaScript 实现继承和共享属性与方法的基础。
- 原型查找:当访问对象的属性或方法时,如果对象本身没有定义,会沿着原型链向上查找,直到找到或到达链的顶端(
null
)。
通过理解原型链,你可以更好地掌握 JavaScript 中的继承机制和对象属性查找过程。