.isPrototypeOf()和.hasOwnProperty()方法混淆

时间:2016-09-11 06:16:51

标签: javascript

假设我有这段代码:

// Male will inherit ALL of the Human properties
function Human(x, y) {
  // Following properties will be inherited
  this.name = x;
  this.age = y;
  this.test = "Test 1";
}
// Following properties will ALSO be inherited
Human.prototype.citizen = "USA";
Human.prototype.employer = "Google";
Human.prototype.test = "Test 2";

function Male(x, y) {
  // Following properties will be the own properties of Male instances
  this.name = x;
  this.age = y;
  this.gender = "Male";
}

// Inheritance - Connecting Male object with Human object
Male.prototype = new Human(); // no arguments are passed
Male.prototype.constructor = Male; // correcting constructor property

var albert = new Male("Albert", 25);

然后,我想对代码进行一些测试

Human.isPrototypeOf(albert); // I expect it to return TRUE

但它返回FALSE,为什么会这样?

并且,对于以下测试

Human.hasOwnProperty("age"); // /i expect it to return TRUE

但它返回FALSE,为什么会这样?

谢谢,

修改 我的问题与另一个问题略有不同,因为它也讨论了原型链。

1 个答案:

答案 0 :(得分:7)

Human原型链中albert函数不是Human.prototype引用的对象是:

Human.prototype.isPrototypeOf(albert); // true
  

Human.hasOwnProperty( “年龄”); //我希望它返回TRUE

Human函数没有age属性。由new创建的实例执行:

new Human().hasOwnProperty("age"); // true

旁注:您设置继承链的方式很常见,并在很多示例中显示,但在两个方面不正确:

  1. 您不想使用new Human来创建Male.prototype

  2. 想要从Human致电Male

  3. 所以:

    function Male(x, y) {
        // Give Human its chance to initialize the object (#2)
        Human.call(this, x, y);
        // ...
    }
    
    // Don't use new Human to create the prototype (#1)
    Male.prototype = Object.create(Human.prototype);
    Male.prototype.constructor = Male;
    

    您不使用new HumanMale创建原型的原因很简单:Human需要参数,但您无需提供参数。

    这是更新的ES5及该代码的早期版本:

    function Human(name, age) { // Argument names should be meaningful
      this.name = name;
      this.age = age;
      this.test = "Test 1";
    }
    
    Human.prototype.citizen = "USA";
    Human.prototype.employer = "Google";
    Human.prototype.test = "Test 2";
    
    function Male(name, age) {
      Human.call(this, name, age);
      this.gender = "Male";
    }
    
    Male.prototype = Object.create(Human.prototype);
    Male.prototype.constructor = Male;
    
    var albert = new Male("Albert", 25);
    console.log(Human.prototype.isPrototypeOf(albert)); // true
    console.log(new Human().hasOwnProperty("age"));     // true

    当然,也可以使用ES2015 +(如果您的目标尚不支持,请进行转换):

    // THIS SNIPPET REQUIRES A BROWSER WITH ES2015+ SUPPORT
    
    class Human {
      constructor(name, age) {
        this.name = name;
        this.age = age;
        this.test = "Test 1";
      }
    }
    
    Human.prototype.citizen = "USA";
    Human.prototype.employer = "Google";
    Human.prototype.test = "Test 2";
    
    class Male extends Human {
      constructor(name, age) {
        super(name, age);
        this.gender = "Male";
      }
    }
    
    let albert = new Male("Albert", 25);
    console.log(Human.prototype.isPrototypeOf(albert)); // true
    console.log(new Human().hasOwnProperty("age"));     // true

    你说过你正试图看看连锁店是如何运作的。以下是创建albert后我们在内存中的图表(为简单起见,删除了一些详细信息):

             +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
             |                                                                      |
             \ +−−−−−−−−−−−−−−−−+                                                   |
    Human−−−−−>|    function    |                                                   |
               +−−−−−−−−−−−−−−−−+                            +−−−−−−−−−−−−−−−−−−−−+ |
               | prototype      |−−−−−−−−−−−−−−−−−−−−−−−−−−−>|       object       | |    
               | name: "Human"  |                          / +−−−−−−−−−−−−−−−−−−−−+ |    
               +−−−−−−−−−−−−−−−−+                          | | constructor        |−+
                                                           | | citizen: "USA"     |
             +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ | | employer: "Google" |
             |                                           | | | test: "Test 2"     |
             \ +−−−−−−−−−−−−−−−−+                        | | +−−−−−−−−−−−−−−−−−−−−+
    Male−−−−−−>|    function    |                        | |
               +−−−−−−−−−−−−−−−−+    +−−−−−−−−−−−−−−−−−+ | |
               | prototype      |−−−>|     object      | | |
               | name: "Male"   |  / +−−−−−−−−−−−−−−−−−+ | |
               +−−−−−−−−−−−−−−−−+  | | constructor     |−+ |
                                   | | [[Prototype]]   |−−−+
               +−−−−−−−−−−−−−−−−+  | +−−−−−−−−−−−−−−−−−+
    albert−−−−>|     object     |  |
               +−−−−−−−−−−−−−−−−+  |
               | name: "Albert" |  |
               | age: 25        |  |
               | gender: "Male" |  |
               | [[Prototype]]  |−−+
               +−−−−−−−−−−−−−−−−+ 
    
    上面的

    [[Prototype]]是规范用于包含对其原型对象的引用的对象的“内部槽”的名称。相比之下,prototype,函数上的属性(例如,Human.prototype),只是函数的正常属性,指向new将用作[[Prototype]]的对象如果将该函数与new一起使用,则会创建新对象。

    该图表上的一些注释:

    • 所有函数都有一个[[Prototype]]内部插槽,指向对象Function.prototype指向(为简单起见,上面省略)。
    • Human,该函数具有name属性:"Human"
    • Male,该函数具有name属性:"Male"
    • 对象albert引用的属性为name"Albert"
    • albert的{​​{1}}是[[Prototype]]; Male.prototype的{​​{1}}是Male.prototype(而[[Prototype]]的{​​{1}}(未显示)是“Object.prototype”。

    你在评论中说过:

      

    我只是无法理解为什么在继承声明之后我们可以Human.prototype返回Human.prototype而不是[[Prototype]](它返回Male.prototype.isPrototypeOf(albert)),因为trueHuman.isPrototypeOf(albert)

    的实例

    因为false,函数在Male.prototype的原型链中无处可去。让我们看看Human的原型链:

    • Human的{​​{1}}是albert
    • albert的{​​{1}}是albert
    • [[Prototype]]的{​​{1}}是Male.prototype
    • Male.prototype的{​​{1}}是[[Prototype]]

    如图:

    +−−−−−−−−−−−−−−−+    +−−−−−−−−−−−−−−−−+    +−−−−−−−−−−−−−−−−−+    +−−−−−−−−−−−−−−−−−−−−−+ 
    |    albert     |    | Male.prototype |    | Human.prototype |    |  Object.prototype   |
    +−−−−−−−−−−−−−−−+    +−−−−−−−−−−−−−−−−+    +−−−−−−−−−−−−−−−−−+    +−−−−−−−−−−−−−−−−−−−−−+ 
    | [[Prototype]] |−−−>| [[Prototype]]  |−−−>| [[Prototype]]   |−−−>| [[Prototype]]: null |
    +−−−−−−−−−−−−−−−+    +−−−−−−−−−−−−−−−−+    +−−−−−−−−−−−−−−−−−+    +−−−−−−−−−−−−−−−−−−−−−+ 
    

    因此Human.prototype,该函数无处可去。