面试题答案
一键面试原型链工作原理
在JavaScript中,每个函数都有一个prototype
属性,这个属性是一个对象,它包含了可以由特定类型的所有实例共享的属性和方法。当使用new
关键字调用构造函数来创建一个新对象时,新对象会有一个内部属性[[Prototype]]
(在现代JavaScript中可以通过__proto__
访问,但更推荐使用Object.getPrototypeOf()
方法),这个内部属性会指向构造函数的prototype
对象。
当访问对象的属性或方法时,JavaScript引擎首先会在对象自身上查找。如果没有找到,它会沿着[[Prototype]]
链向上查找,直到找到该属性或方法,或者到达原型链的顶端(null
)。如果到达顶端仍未找到,访问会返回undefined
。
通过原型链实现属性和方法继承的示例
// 定义一个父构造函数
function Animal(name) {
this.name = name;
}
// 在Animal的原型上定义一个方法
Animal.prototype.speak = function() {
console.log(this.name + ' makes a sound.');
};
// 定义一个子构造函数,继承自Animal
function Dog(name, breed) {
// 调用父构造函数来初始化name属性
Animal.call(this, name);
this.breed = breed;
}
// 设置Dog的原型为Animal的实例,从而实现继承
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
// 在Dog的原型上定义一个新方法
Dog.prototype.bark = function() {
console.log(this.name + ' barks.');
};
// 创建一个Dog实例
const myDog = new Dog('Buddy', 'Golden Retriever');
// 访问继承自Animal的属性和方法
myDog.speak(); // 输出: Buddy makes a sound.
// 访问Dog自身的属性和方法
console.log(myDog.breed); // 输出: Golden Retriever
myDog.bark(); // 输出: Buddy barks.
在上述示例中,Dog
构造函数通过设置其原型为Animal.prototype
的一个实例,从而继承了Animal
的属性和方法。myDog
实例在查找speak
方法时,由于自身没有该方法,会沿着原型链找到Animal.prototype
上的speak
方法并执行。同时,Dog
自身也可以定义特有的属性(如breed
)和方法(如bark
)。