代码之家  ›  专栏  ›  技术社区  ›  Upgradingdave

关于Object.create()和属性继承的混淆

  •  2
  • Upgradingdave  · 技术社区  · 6 年前

    在下面的片段中,为什么 boat.calls sailboat.getHasEngine() ? 还有,为什么 sailboat.calls

    let vehicle = {
      calls: 0,
      hasEngine: null,
      getHasEngine: function() {
        vehicle.calls = vehicle.calls + 1;
        this.calls = this.calls + 1;
        return this.hasEngine;
      },
      canFly: null,
      getCanFly: function() { 
        vehicle.calls = vehicle.calls + 1;
        this.calls = this.calls + 1;
        return this.canFly; 
      }
    }
    
    let boat = Object.create(vehicle);
    boat.canFly = false;
    
    let sailboat = Object.create(boat);
    sailboat.hasEngine = false;
    
    let fishingBoat = Object.create(boat);
    fishingBoat.hasEngine = true;
    
    console.log(vehicle.calls);
    // 0
    console.log(boat.calls);
    // 0
    console.log(sailboat.calls);
    // 0
    
    sailboat.getHasEngine();
    
    console.log(vehicle.calls);
    // 1
    console.log(boat.calls);
    // 1
    console.log(sailboat.calls);
    // 2
    1 回复  |  直到 6 年前
        1
  •  5
  •   T.J. Crowder    6 年前

    因为这条线 getHasEngine :

    vehicle.calls = vehicle.calls + 1;
    

    直接访问 vehicle boat 没有自己的 calls 属性,它从 车辆 boat.calls 是1。

    还有,为什么 sailboat.calls 仅呼叫后设置为2 getHasEngine() 一次?

    也因为这条线:它设定 vehicle.calls 1 ,到那时, sailboat 电话 ,因此它继承了属性。然后在下一行:

    this.calls = this.calls + 1;
    

    那是 阅读 车辆呼叫 帆船.呼叫 .

    getHasEngine公司

                                                              +−−−−−−−−−−+
    vehicle−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+−−>| (object) |
                                                          |   +−−−−−−−−−−+
                                                          |   | calls: 0 |
                                                          |   +−−−−−−−−−−+
                                       +−−−−−−−−−−−−−−−+  | 
    boat−−−−−−−−−−−−−−−−−−−−−−−−−−−+−−>|   (object)    |  | 
                                   |   +−−−−−−−−−−−−−−−+  | 
                                   |   | [[Prototype]] |−−+ 
                                   |   +−−−−−−−−−−−−−−−+     
                                   |
                +−−−−−−−−−−−−−−−+  |
    sailboat−−−>|   (object)    |  |
                +−−−−−−−−−−−−−−−+  |
                | [[Prototype]] |−−+
                +−−−−−−−−−−−−−−−+      
    

    请注意,两者都不是 也不是 帆船 有一个 电话 财产。

    之后 getHasEngine公司 帆船 电话 属性(因为它是由 this.calls = this.calls + 1;

                                                              +−−−−−−−−−−+
    vehicle−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+−−>| (object) |
                                                          |   +−−−−−−−−−−+
                                                          |   | calls: 1 |
                                                          |   +−−−−−−−−−−+
                                       +−−−−−−−−−−−−−−−+  | 
    boat−−−−−−−−−−−−−−−−−−−−−−−−−−−+−−>|   (object)    |  | 
                                   |   +−−−−−−−−−−−−−−−+  | 
                                   |   | [[Prototype]] |−−+ 
                                   |   +−−−−−−−−−−−−−−−+     
                                   |
                +−−−−−−−−−−−−−−−+  |
    sailboat−−−>|   (object)    |  |
                +−−−−−−−−−−−−−−−+  |
                | [[Prototype]] |−−+
                | calls: 2      |
                +−−−−−−−−−−−−−−−+      
    

    下面是一个带有日志记录的版本,有助于显示:

    let vehicle = {
      calls: 0,
      hasEngine: null,
      getHasEngine: function() {
        console.log("updating vehicle.calls");
        vehicle.calls = vehicle.calls + 1;
        console.log("vehicle.calls is now vehicle.calls");
        console.log("About to update this.calls, does this have calls?", this.hasOwnProperty("calls"));
        this.calls = this.calls + 1;
        console.log("Just updated this.calls, does this have calls?", this.hasOwnProperty("calls"));
        return this.hasEngine;
      },
      canFly: null,
      getCanFly: function() { 
        vehicle.calls = vehicle.calls + 1;
        this.calls = this.calls + 1;
        return this.canFly; 
      }
    }
    
    let boat = Object.create(vehicle);
    boat.canFly = false;
    
    let sailboat = Object.create(boat);
    sailboat.hasEngine = false;
    
    let fishingBoat = Object.create(boat);
    fishingBoat.hasEngine = true;
    
    console.log(vehicle.calls);  // 0
    console.log(boat.calls);     // 0
    console.log("boat has calls?", boat.hasOwnProperty("calls"));
    console.log(sailboat.calls); // 0
    console.log("sailboat has calls?", sailboat.hasOwnProperty("calls"));
    
    sailboat.getHasEngine();
    
    console.log(vehicle.calls);  // 1
    console.log(boat.calls);     // 1
    console.log("boat has calls?", boat.hasOwnProperty("calls"));
    console.log(sailboat.calls); // 2
    console.log("sailboat has calls?", sailboat.hasOwnProperty("calls"));
    .as-console-wrapper {
      max-height: 100% !important;
    }

    如果你移除 vehicle.calls = 行,你看它停止发生:

    let vehicle = {
      calls: 0,
      hasEngine: null,
      getHasEngine: function() {
        //vehicle.calls = vehicle.calls + 1;
        this.calls = this.calls + 1;
        return this.hasEngine;
      },
      canFly: null,
      getCanFly: function() { 
        //vehicle.calls = vehicle.calls + 1;
        this.calls = this.calls + 1;
        return this.canFly; 
      }
    }
    
    let boat = Object.create(vehicle);
    boat.canFly = false;
    
    let sailboat = Object.create(boat);
    sailboat.hasEngine = false;
    
    let fishingBoat = Object.create(boat);
    fishingBoat.hasEngine = true;
    
    console.log(vehicle.calls);  // 0
    console.log(boat.calls);     // 0
    console.log(sailboat.calls); // 0
    
    sailboat.getHasEngine();
    
    console.log(vehicle.calls);  // 0
    console.log(boat.calls);     // 0
    console.log(sailboat.calls); // 1