我创建了一个例子来说明:
// this is the parent class
function animal() { console.log('animal constructor') }
// allow animals to walk
animal.prototype.walk = function() { console.log('animal walking') }
// create child class
function cat() { console.log('cat constructor') }
// cat inherits from animal
cat.prototype = Object.create(animal.prototype);
// let cats meow
cat.prototype.meow = function() { console.log('meow') }
// create a cat object
var myCat = new cat();
/* output: cat constructor */
// yet, the constructor that ran is different than what the prototype for cat reports
console.log(cat.prototype.constructor);
/* output: function animal() { console.log('animal constructor') } */
请注意,继承主要如何按预期工作,cat从其父类继承了方法'walk',并向子类添加了更多方法,如meow按预期工作。但是,当我创建cat的实例时,cat的构造函数会运行,而cat.prototype.constructor指向从dog继承的构造函数。
object.prototype.constructor的目的是否允许我们在声明对象之后修改对象的构造函数而不擦除对象的原型?在上面的例子中,cat.prototype.constructor中存储的构造函数是否应该指向创建cat对象时运行的相同构造函数?这种明显的歧义是否与this source code此语句的运行方式有关:
// Enforce the constructor to be what we expect
Class.prototype.constructor = Class;
答案 0 :(得分:4)
constructor
属性只是原型对象的一个简单属性。幕后没有任何神奇的事情发生。它是一个可以被覆盖和重置的属性,但它不会影响其他任何东西。
所以当你这样做时:
cat.prototype = Object.create(animal.prototype);
您将使用从cat
prototype
对象派生的完整新对象覆盖函数animal
的整个原型属性。但由于constructor
属性只是prototype
对象的普通属性,因此它也会被覆盖。
是的,在实现继承时,行
Class.prototype.constructor = Class;
通常会添加以将constructor
属性恢复为其原始值,并撤消此继承模式所做的“损坏”。
因此,在您的情况下,您需要添加以下行:
cat.prototype = Object.create(animal.prototype);
cat.prototype.constructor = cat; // <---- add this
答案 1 :(得分:0)
想想这一行:
cat.prototype = Object.create(animal.prototype);
Object.create(animal.prototype)
将只返回一个本身没有属性但其原型由animal.prototype
给出的对象。因此,在此对象上查找constructor
属性只会返回animal.prototype.constructor
中保存的值。
由于上面的行将这个新创建的对象的引用分配给cat.prototype
(因此覆盖之前在cat.prototype
中保存的内容),当然你期望cat.prototype.constructor
到animal.prototype.constructor
等于cat.prototype.constructor = cat;
。
正如您上面提到的,您可以使用以下内容来解决这个“问题”:
{{1}}
Object.create()的参考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create