簡體   English   中英

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

[英].isPrototypeOf() and .hasOwnProperty() method confusion

假設我有這個代碼:

 // 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,為什么呢?

謝謝,

編輯我的問題與其他問題略有不同,因為它也談論原型鏈。

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. 想叫HumanMale

所以:

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[[Prototype]]Male.prototype ; Male.prototype[[Prototype]]Human.prototype (和Human.prototype[[Prototype]] ,未顯示,是`Object.prototype)。

你在評論中說過:

我只是無法理解為什么繼承語句后我們可以做Male.prototype.isPrototypeOf(albert)返回true而不是Human.isPrototypeOf(albert) (它返回false )因為Male.prototypeHuman一個實例

因為Human ,這個功能,在albert的原型鏈中是無處可去的。 讓我們看看albert的原型鏈:

  • albert[[Prototype]]Male.prototype
  • Male.prototype[[Prototype]]Human.prototype
  • Human.prototype[[Prototype]]Object.prototype
  • Object.prototype[[Prototype]]null

如圖:

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

因此, Human ,這個功能,在這個鏈條中無處可去。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM