JavaScript继承原型链关系验证及代码结果疑问求助
一、继承关系表的错误修正
咱们先把你整理的继承关系逐一拆解,指出需要修正的地方:
错误1:
compare ---prototype---> Animal.prototype(constructor,run)compare是Animal的静态方法,本质是挂载在Animal构造函数上的普通函数。函数的prototype属性是一个默认包含constructor的空对象(除非手动修改),而compare的[[prototype]](即__proto__)指向的是Function.prototype,和Animal.prototype没有直接关联。错误2:
Rabbit ---[[prototype]]---> compare
当使用class Rabbit extends Animal时,子类构造函数Rabbit的[[prototype]](__proto__)指向的是父类构造函数Animal,而不是Animal的静态方法compare。静态方法是子类从父类构造函数继承来的,但Rabbit的原型链顶端是Animal本身,不是单个静态方法。错误3:
Rabbit ---prototype---> AnimalRabbit作为构造函数,它的prototype属性是Rabbit.prototype对象(专门给实例提供方法的原型对象),而不是Animal构造函数本身。正确的关系是Rabbit.prototype.__proto__ === Animal.prototype。错误4:
rabbit(name:'White Rabbit') ---prototype---> Rabbit
只有函数(构造函数)才有prototype属性,普通实例对象rabbit是没有prototype的。你想表达的应该是rabbit.__proto__ === Rabbit.prototype,这条是正确的。
剩下的两条关系是完全正确的:
Rabbit.prototype ---[[prototype]]---> Animal.prototype(constructor,run)rabbit(name:'White Rabbit') ---[[prototype]]---> Rabbit.prototype
二、代码疑问解答
先看你最后一行有疑问的代码:
console.log(rabbits[1].__proto__ === Animal.prototype); // 此处有问题
这条输出结果是false,完全符合JS继承的规则,原因很直观:
rabbits[1]是Rabbit类的实例,它的[[prototype]](__proto__)直接指向Rabbit.prototype——这是JS实例继承的基础规则:实例的直接原型永远是它所属构造函数的prototype对象。- 而
Rabbit.prototype的[[prototype]]才指向Animal.prototype,所以如果要判断实例和父类原型的关系,需要多走一层原型链:
用更规范的console.log(rabbits[1].__proto__.__proto__ === Animal.prototype); // 输出 trueObject.getPrototypeOf方法写的话是这样:console.log(Object.getPrototypeOf(Object.getPrototypeOf(rabbits[1])) === Animal.prototype); // true
你之所以觉得不符合预期,大概率是混淆了实例的直接原型和原型链上的父类原型,把两层关系当成了一层。
内容的提问来源于stack exchange,提问作者user11264432

