获取原型链中对象名称:JavaScript原型继承输出异常排查
问题分析与解决方案
为什么会得到Animal、Animal、Animal、Object的输出?
核心问题出在你设置Cat原型的方式和constructor属性的指向错误:
- 当你执行
Cat.prototype = new Animal();时,你把Cat的原型对象替换成了一个Animal的实例。这个Animal实例的constructor属性默认指向Animal构造函数(因为所有Animal实例的原型链都会指向Animal.prototype,而Animal.prototype.constructor默认是Animal)。 - 当你访问
cat1.constructor时,因为cat1本身没有constructor属性,会顺着原型链查找,找到Cat的原型(那个Animal实例)的constructor,也就是Animal。 - 接下来的循环中:
- 第一个
currentPrototype是cat1,输出Animal; - 第二个
currentPrototype是cat1的原型(Animal实例),它的constructor还是Animal; - 第三个
currentPrototype是Animal.prototype,它的constructor默认就是Animal; - 最后到
Object.prototype,输出Object。
- 第一个
这就导致了你看到的重复Animal输出。
你的原型继承写法存在哪些问题?
用new Animal()作为子类的原型是一种过时且有缺陷的写法:
- 会不必要地执行父类的构造函数,导致父类构造函数中定义的实例属性(比如
name、age、eat、getAge)被加到子类的原型上,这些属性应该属于子类实例,而不是原型; - 子类原型的
constructor属性没有修正,导致实例的constructor指向错误,无法正确反映实例的构造函数类型; - 每个实例都会创建独立的
eat、getAge、hunt函数,浪费内存(这些方法应该放到原型上共享)。
如何修正代码得到正确结果?
我们需要用更规范的原型继承方式,同时修正constructor指向:
修正后的完整代码:
function Animal(name, age){ this.name = name; this.age = age; } // 将方法放到原型上,让所有实例共享 Animal.prototype.eat = function(){ console.log(this.name + " eats"); }; Animal.prototype.getAge = function(){ console.log(this.name + " is " + this.age + " years old"); }; function Cat(name, age){ // 调用父类构造函数,初始化实例属性 Animal.call(this, name, age); } // 用Object.create创建以Animal.prototype为原型的对象,避免执行父类构造函数 Cat.prototype = Object.create(Animal.prototype); // 手动修正constructor指向,让Cat实例的constructor回到Cat Cat.prototype.constructor = Cat; // 给Cat添加独有的原型方法 Cat.prototype.hunt = function(){ console.log(this.name + " hunts mice"); }; var cat1 = new Cat("cat1", 2); var currentPrototype = cat1; while(currentPrototype != null){ console.log(currentPrototype.constructor.name); currentPrototype = Object.getPrototypeOf(currentPrototype); }
修正后的输出:
Cat Animal Object
关键修正点说明:
Object.create(Animal.prototype):创建一个空对象,其原型直接指向Animal.prototype,不会执行Animal的构造函数,避免了父类实例属性污染子类原型的问题。Cat.prototype.constructor = Cat:因为Object.create创建的对象默认constructor是Object,所以必须手动修正回Cat,这样实例的constructor才能正确指向自己的构造函数。- 将方法移到原型上:所有实例共享同一个方法,节省内存,这是原型继承的最佳实践。
内容的提问来源于stack exchange,提问作者KGS
相关产品推荐
相关产品推荐

