这个问题是关于javascript原型如何工作的。特别是我不明白为什么在下面的例子中“机器”似乎有自己的原型。
在Chrome Web Tools控制台的屏幕截图中,Machine __proto __对象似乎引用了与其父级相同的功能。您将看到一个“__proto __:Machine”,其属性为“whoAmI”,第二个属性为“__proto __:Machine”。钻入第二个“__proto __”会显示一个构造函数和包含Object的“__proto __”但没有属性“whoAmI”。
对“机器”的双重引用是什么意思,为什么只有其中一个包含whoAmyI属性?
function Car(){}
function Vehicle() {}
function Machine() {
this.whoAmI = 'I am a machine';
}
Vehicle.prototype = new Machine();
Car.prototype = new Vehicle();
var myCar = new Car();
Chrome网络工具截屏:
答案 0 :(得分:3)
最好使用Object.create而不是创建Parent的实例来设置Child的原型(至少)2个原因。
定义子类型时,您可能不希望此时创建Parent实例,因为此时应用程序的状态尚未准备好创建父类型的实例(如需要的依赖项)传递给父构造函数,在定义Child时不可用。
Parent具有特定于实例的成员(Parent构造函数中的任何this.something =
),并且创建Parent的实例会将这些特定于实例的成员放在Child.prototype上。
这就是为什么你看到Machine(一个类型为Machine的实例),其中whoAmi成员和Machine作为此Machine实例的__proto__
。
以下代码可能会产生您期望的输出,并且因为在设置继承的原型部分后修复了构造函数,它会显示正确的名称:
function Car(){
//re use parent constructor
Vehicle.call(this);
//extend whoAmi
this.whoAmI = this.whoAmI + ' and a Car';
}
function Vehicle() {
//re use parent constructor
Machine.call(this);
//extend whoAmi
this.whoAmI = this.whoAmI + ' and a Vehicle';
}
function Machine() {
this.whoAmI = 'I am a machine';
}
Vehicle.prototype = Object.create(Machine.prototype);
Vehicle.prototype.constructor = Vehicle;
Car.prototype = Object.create(Vehicle.prototype);
Car.prototype.constructor = Car;
var myCar = new Car();
console.dir(myCar);
在创建某种类型的实例时,也许following answer可以帮助理解原型和构造函数(或init)的作用:
答案 1 :(得分:1)
如果我理解你的问题,那么简短的回答:它实际上不是一个自我引用。定义函数时,它上面的prototype属性被初始化为一个新对象,其constructor
属性指向正在定义的函数。您在Vehicle
和Car
函数上覆盖了此原型对象,但未覆盖Machine
函数。由于我不知道的原因,Chrome将函数的默认原型属性的类型命名为与函数名称相同。 IE将其称为[object (Machine)]
,Firefox仅将其称为Object
。
回顾一下:myCar
将__proto__
设置为Car.prototype
,这是Vehicle
个实例,其__proto__
设置为Vehicle.prototype
,这是一个Machine
实例(具有whoAmI
属性),其__proto__
设置为Machine.prototype
,这是一个具有constructor
属性的对象, Chrome(不幸的是?必须有一个原因......)与constructor
属性指向的函数同名。
这就是为什么那里有额外的“机器”对象,但我不能告诉你为什么Chrome会把它称之为它。