JavaScript >> Javascript 文檔 >  >> Tags >> object

確定對象屬性是否存在

開發人員在 JavaScript 中執行的最基本測試之一是對像上是否存在特定屬性。由於特徵檢測是代碼分叉的首選方法,因此鼓勵開發人員在使用屬性之前測試它們是否存在。由於沒有經驗的開發人員嘗試使用特徵檢測,因此有很多錯誤的 JavaScript 代碼。很多問題在於對 JavaScript 中對象屬性的本質缺乏了解。

屬性從何而來?

在嘗試檢測屬性之前,了解它們的來源很重要。 JavaScript 中有兩種基本類型的屬性:存在於對像上的屬性(也稱為“自己的”屬性)和通過原型鏈繼承的屬性(通常稱為“原型”屬性)。考慮以下幾點:

var person = {
    name: "Nicholas"
};

alert(person.name);        //"Nicholas"
alert(person.toString());  //"[object Object]"

在這段代碼中,對象 person 只有一個自己的屬性,即 name .您仍然可以訪問對像上的其他方法,例如 toString() ,但這些都是通過原型鏈繼承的。對象字面量繼承自 Object type,所以Object的所有基本方法 可以在實例上訪問。

自有屬性和原型屬性之間的最大區別在於唯一值和共享值之間的區別。自己的屬性屬於該單個對象實例,不受其他同類型實例的影響;原型屬性屬於對象的原型,由於原型可以在多個實例之間共享,因此這些屬性也可以在多個實例之間共享。這是另一個例子:

var person2 = Object.create(person);
var person3 = Object.create(person);

alert(person2.name);   //"Nicholas"
alert(person3.name);   //"Nicholas"

person.name = "Adam";

alert(person2.name);    //"Adam"
alert(person3.name);    //"Adam"

此示例使用 <a href="http://javascript.crockford.com/prototypal.html">Object.create()</a> 來自 ECMAScript 5 的方法來創建兩個對象,person2person3 , 繼承自 person . person2 的原型 和 person3person ,所以 name 實際上是一個原型屬性,可以通過 person2 訪問 和 person3 .這就是為什麼在兩個對像上顯示 name 的值會導致相同的值:它們都共享原型屬性 name .這意味著當 person.name 直接更改,可以從實例中訪問更改。

了解 name 很重要 是兩個 person2 的原型屬性 和 person3 , 但它是 person 的自己的屬性 .您只能將值分配給自己的屬性,因此嘗試為原型屬性分配值實際上會導致創建一個新的同名屬性。示例:

alert(person2.name);    //"Nicholas"
alert(person3.name);    //"Nicholas"

person2.name = "Adam";

alert(person2.name);    //"Adam"
alert(person3.name);    //"Nicholas"

由於您不能分配給原型屬性,因此為 person2.name 分配一個新值 實際上在 person2 上創建了一個新的自己的屬性 稱為 name .自己的屬性總是隱藏原型屬性,所以下次訪問 person2.name ,您訪問的是自己的屬性而不是原型屬性。這將一直持續到使用 delete 刪除自己的屬性 ,如:

delete person2.name;

alert(person2.name);    //"Nicholas"

你只能調用 delete 在自己的屬性上刪除它(調用原型屬性什麼都不做)。一旦擁有自己的屬性name 被刪除,原型屬性 name 沒有任何陰影 所以 person2.name 現在指原型屬性。

注意:雖然所有原生對像類型 (Array , Boolean , Date , 所有 Error 變體,Function , Number , RegExp , 和 String ) 繼承自 Object ,非本地對像類型,例如那些在瀏覽器中表示 DOM 的對像類型,不一定繼承自 Object 在所有瀏覽器中。

檢測屬性

假設您想確定給定對像是否具有名稱屬性。在有經驗的開發者中,往往會寫出這樣的代碼:

//doesn't accurately test for existence
if (person.name){
    //yay! property exists!
}

乍一看,這似乎沒問題。但是,了解 JavaScript 的工作原理會發現這種方法存在一些問題。首先,只有 person.name 的值才會成功 是真實的,這意味著它是一個對象、一個非空字符串、一個非 NaN 的非零數字 , true ,而不是 nullundefined .這意味著如果 person.name 是空字符串(“”),此檢查將失敗。在這種情況下,失敗並不意味著該屬性不存在。事實上,該屬性確實存在並包含一個值,但該值是假的,因此沒有通過這個測試。

檢測自己的屬性

請記住,這是關於測試存在 屬性而不是可用性或數據類型,有幾個選項。第一個選項是檢測自己的屬性,它通過 Object 上的方法來 名為 hasOwnProperty() 的類型 .由於原生對象繼承自 Object ,這個屬性被這些對象繼承,可以用來檢測自己的屬性是否存在:

alert(person.hasOwnProperty("name"));   //true
alert(person2.hasOwnProperty("name"));    //false

person2.name = "Adam";

alert(person2.hasOwnProperty("name"));    //true

delete person2.name;

alert(person2.hasOwnProperty("name"));    //false

最初,person2 有一個原型屬性 name ,所以 hasOwnProperty() 返回假。創建自己的屬性後,調用 hasOwnProperty() 返回真。並且在通過 delete 刪除該屬性之後 ,此方法再次返回false。

JSON 序列化僅適用於自己的屬性,非本機 JSON 序列化實用程序使用 hasOwnProperty() 確保只有在對象字面量上定義的屬性才包含在結果字符串中。

檢測所有屬性

如果只關心對像有屬性,不關心是自己的屬性還是原型屬性,可以使用in 運算符來確定屬性的存在。示例:

if ("name" in person){
    //property exists
}

in 當對像上存在命名屬性時,運算符返回 true。在許多情況下,in 運算符就是您所需要的(尤其是在處理 DOM 對象時)。事實上,Mark Pilgrim 的 All-In-One Near-Alphabetical No-Bullshit Guide to Detecting Everything for HTML5 廣泛使用了 in 用於檢測 DOM 對像上的新 HTML5 功能。

結論

如果您只想檢查屬性是否存在,而不一定要檢查它們的值,那麼您有兩個安全的選擇:hasOwnProperty()in 操作員。 hasOwnProperty() 如果您只想檢測自己的屬性,則應使用屬性方法。如果你想測試屬性是否存在而不關心它是一個自己的屬性還是一個對象的屬性,那麼 in 運算符是要使用的。

更新(2010 年 7 月 27 日): 添加了 falseNaN 到虛假值列表。**

更新(2010 年 7 月 29 日): 修正了真/假值的描述。

更新(2012 年 12 月 22 日): 修復了指向 Mark Pilgrim 列表的鏈接。


Tutorial JavaScript 教程
  1. 第 91 天:登陸頁面設計和實施。

  2. 使用 Detox 在 React Native 中進行端到端測試

  3. 在 JavaScript 中將字符轉換為 ASCII 碼

  4. 如何遍曆本地(服務器端)文件夾的所有元素?

  5. 按數組中的數組對對象進行排序?

  6. “執行者”和傳遞給 then() 方法的函數之間有什麼關係(如果有的話)? [關閉]

  7. 🎉 Deno:1.0 正式預定 5 月 13 日!功能回顧

  1. 什麼是 JavaScript 運行時?

  2. 如何通過 4 個步驟構建股票圖表 (JS)

  3. 簡單的 JavaScript 循環

  4. 使用 Vue.js 和 Parse 平台構建 Todoist 應用程序(第 2 部分 - 登錄)

  5. 我在我的投資組合主頁中添加了一個 JavaScript 街機遊戲

  6. 從長遠來看,我應該選擇 JS 還是 Python?

  7. 在 React.js 中滾動時隱藏菜單

  1. React Ref 添加類名

  2. Mongooses `save()` 函數簡介

  3. 從零開始搭建灰度發布環境

  4. 10 個很棒的 jQuery 技術和效果