关于Object.create()和属性继承的困惑

时间:2018-11-06 18:43:24

标签: javascript

在下面的代码段中,为什么我呼叫Documentboat.calls会增加?另外,为什么只调用一次getHasEngine()后sailboat.getHasEngine()设置为2?

sailboat.calls

1 个答案:

答案 0 :(得分:5)

由于getHasEngine中的这一行:

vehicle.calls = vehicle.calls + 1;

那是直接访问vehicle对象。由于boat没有自己的calls属性,因此它是从vehicle继承的,因此boat.calls为1。

  

还有,为什么只调用一次sailboat.callsgetHasEngine()设置为2?

也因为该行:将vehicle.calls设置为1,并且此时sailboat没有自己的calls,因此它继承了该属性。然后在下一行执行以下操作:

this.calls = this.calls + 1;

正在读取 vehicle.calls(1),向其添加1,然后将结果(2)分配给sailboat.calls

让我们扔一些ASCII艺术。创建对象之后但在调用getHasEngine之前,您已经在内存中保存了此信息(省略了详细信息):

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

请注意,boatsailboat都没有calls属性。

调用一次getHasEngine之后,您将具有以下条件-请注意,sailboat现在具有calls属性(因为它是由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