面试题答案
一键面试- 原型链在属性查找中的作用:
- 当访问一个对象的属性时,JavaScript 引擎首先在该对象本身的属性中查找。如果找到了该属性,就直接返回该属性的值。
- 如果在对象本身没有找到该属性,引擎会沿着原型链向上查找。每个对象都有一个
[[Prototype]]
(在现代 JavaScript 中可以通过__proto__
访问,更推荐使用Object.getPrototypeOf()
方法),指向它的原型对象。引擎会在原型对象中查找该属性。 - 如果在原型对象中找到了该属性,就返回该属性的值。如果没有找到,继续沿着原型链向上查找,直到到达原型链的顶端(
Object.prototype
)。如果在Object.prototype
中也没有找到该属性,就返回undefined
。
- 不同层级定义相同属性名时的访问结果举例:
// 定义一个构造函数
function Animal() {
this.species = '动物';
}
// 在 Animal 的原型上定义一个属性
Animal.prototype.sound = '通用声音';
// 定义一个 Dog 构造函数,继承自 Animal
function Dog(name) {
this.name = name;
this.species = '狗';// 这里 Dog 实例自身定义了与原型不同值的 species 属性
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
// 创建一个 Dog 实例
let myDog = new Dog('旺财');
// 访问 name 属性,在 Dog 实例本身找到
console.log(myDog.name); // '旺财'
// 访问 species 属性,在 Dog 实例本身找到,尽管原型上也有,但优先使用实例自身的
console.log(myDog.species); // '狗'
// 访问 sound 属性,在 Dog 实例本身没找到,在原型(Animal.prototype)中找到
console.log(myDog.sound); // '通用声音'
在上述例子中,myDog
实例查找属性时,首先看自身有没有定义,如果有就使用自身的属性值。比如 name
和 species
属性,myDog
自身有定义,所以直接返回自身的值。而 sound
属性在 myDog
自身没有定义,就沿着原型链在 Animal.prototype
中找到了。