Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript原型链自引用_Javascript_Prototype - Fatal编程技术网

Javascript原型链自引用

Javascript原型链自引用,javascript,prototype,Javascript,Prototype,这个问题是关于javascript原型如何工作的。特别是,我不明白为什么在下面的例子中,机器似乎有一个自己的原型 在ChromeWebTools控制台的屏幕截图中,机器的proto对象似乎引用了与其父对象相同的功能。您将看到一个带有属性whoAmI和第二个属性\uuuuuu proto\uuuu:Machine的\uuuuuu:Machine。深入到第二个_proto _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 对机器的双重引用是什么意

这个问题是关于javascript原型如何工作的。特别是,我不明白为什么在下面的例子中,机器似乎有一个自己的原型

在ChromeWebTools控制台的屏幕截图中,机器的proto对象似乎引用了与其父对象相同的功能。您将看到一个带有属性whoAmI和第二个属性\uuuuuu proto\uuuu:Machine的\uuuuuu:Machine。深入到第二个_proto _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

对机器的双重引用是什么意思?为什么其中只有一个包含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 web工具屏幕截图:


最好使用Object.create,而不是创建父对象的实例来设置子对象的原型,至少有两个原因

定义子类型时,此时可能不希望创建父类型的实例,因为应用程序的状态此时不准备创建父类型的实例,例如需要传递给父构造函数的依赖项,而在定义子类型时不可用

父类在父类构造函数中具有任何this.something=的实例特定成员,并且创建父类的实例会将这些实例特定成员放在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);

在创建特定类型的实例时,也许可以帮助理解prototype和构造函数或init的作用:

最好使用Object.create,而不是创建父实例来设置子实例的prototype,至少有两个原因

定义子类型时,此时可能不希望创建父类型的实例,因为应用程序的状态此时不准备创建父类型的实例,例如需要传递给父构造函数的依赖项,而在定义子类型时不可用

父类在父类构造函数中具有任何this.something=的实例特定成员,并且创建父类的实例会将这些实例特定成员放在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);

在创建特定类型的实例时,也许可以帮助理解原型和构造函数或init的作用:

如果我理解您的问题,请简短回答:它实际上不是一个自引用。定义函数时,函数上的prototype属性将初始化为一个新对象,该对象具有指向所定义函数的构造函数属性。您正在覆盖车辆和车辆功能上的此原型对象,但不是机器功能。出于我不知道的原因,Chrome将函数的默认原型属性的类型命名为与函数名称相同的类型。IE将其称为[object Machine],Firefox将其称为object

因此,概括一下:myCar将proto设置为Car.prototype,这是一个将其proto设置为Vehicle.prototype的车辆实例,这是一个具有whoAmI属性的机器实例,该属性将proto设置为Machine.prototype,这是一个具有构造函数属性的对象,不幸的是?一定有原因。。。使用与构造函数属性指向的函数相同的名称引用


这就是为什么会有额外的机器对象,但我无法告诉你为什么Chrome会这么称呼它。

如果我理解你的问题,请简短回答:它实际上不是一个自我引用。定义函数时,函数上的prototype属性将初始化为一个新对象,该对象具有指向所定义函数的构造函数属性。您正在覆盖车辆和车辆功能上的此原型对象,但不是机器功能。出于我不知道的原因,Chrome将函数的默认原型属性的类型命名为与函数名称相同的类型。IE将其称为[object Machine],Firefox将其称为object

因此,概括一下:myCar将proto设置为Car.prototype,这是一个将其proto设置为Vehicle.prototype的车辆实例,这是一个具有whoAmI属性的机器实例,该属性将proto设置为Machine.prototype,这是一个具有构造函数属性的对象,不幸的是?一定有原因。。。使用与构造函数pro指向的函数相同的名称引用 佩蒂


这就是为什么会有额外的机器对象,但我不能告诉你为什么Chrome会这么称呼它。

这只是控制台输出,所以不要读太多。设置继承的首选方法是执行Vehicle.prototype=Object.createMachine.prototype;。这样做,你会在Chrome的控制台中得到不同的标签,即使它基本上是相同的,尽管Vehicle.prototype对象没有whoAmI属性。我认为问题的一部分是Chrome使用.constructor属性来计算标签。设置继承的方式就是破坏原始的.constructor属性。如果您使用Vechicle.prototype.constructor=Vehicle;Car.prototype.constructor=Car;,你应该得到一个更容易理解的输出。那只是控制台输出,所以不要读太多。设置继承的首选方法是执行Vehicle.prototype=Object.createMachine.prototype;。这样做,你会在Chrome的控制台中得到不同的标签,即使它基本上是相同的,尽管Vehicle.prototype对象没有whoAmI属性。我认为问题的一部分是Chrome使用.constructor属性来计算标签。设置继承的方式就是破坏原始的.constructor属性。如果您使用Vechicle.prototype.constructor=Vehicle;Car.prototype.constructor=Car;,你应该得到一个更容易理解的输出。你可以用第二个参数一次性设置构造函数。Car.prototype=Object.createVehicle.prototype,{constructor:value:Car}@naomik是正确的,但第二个参数在某些浏览器ie8中无法多填充。我同意@naomik的观点。只要您要设置.constructor,就可以通过一个调用来完成。第二个参数可以用多边形填充。它是无法模拟的可枚举、可写和可配置描述符。您可以使用第二个参数一次性设置构造函数。Car.prototype=Object.createVehicle.prototype,{constructor:value:Car}@naomik是正确的,但第二个参数在某些浏览器ie8中无法多填充。我同意@naomik的观点。只要您要设置.constructor,就可以通过一个调用来完成。第二个参数可以用多边形填充。它是无法模拟的可枚举、可写和可配置描述符。