Javascript原型链自我引用

时间:2014-11-02 03:29:22

标签: javascript prototype

这个问题是关于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网络工具截屏:

Chrome web tools screen capture

2 个答案:

答案 0 :(得分:3)

最好使用Object.create而不是创建Parent的实例来设置Child的原型(至少)2个原因。

  1. 定义子类型时,您可能不希望此时创建Parent实例,因为此时应用程序的状态尚未准备好创建父类型的实例(如需要的依赖项)传递给父构造函数,在定义Child时不可用。

  2. Parent具有特定于实例的成员(Parent构造函数中的任何this.something =),并且创建Parent的实例会将这些特定于实例的成员放在Child.prototype上。

  3. 这就是为什么你看到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属性指向正在定义的函数。您在VehicleCar函数上覆盖了此原型对象,但未覆盖Machine函数。由于我不知道的原因,Chrome将函数的默认原型属性的类型命名为与函数名称相同。 IE将其称为[object (Machine)],Firefox仅将其称为Object

回顾一下:myCar__proto__设置为Car.prototype,这是Vehicle个实例,其__proto__设置为Vehicle.prototype ,这是一个Machine实例(具有whoAmI属性),其__proto__设置为Machine.prototype,这是一个具有constructor属性的对象, Chrome(不幸的是?必须有一个原因......)与constructor属性指向的函数同名。

这就是为什么那里有额外的“机器”对象,但我不能告诉你为什么Chrome会把它称之为它。