1. 對象的簡單介紹與一些註意事項 JavaScript中具有幾個簡單數據類型:數字、字元串、布爾值、null值以及undefined值。除此之外其餘所有值(包括數組、函數,甚至正則表達式)都是對象。數字、字元串以及布爾值錶面是對象(因為他們具有方法),但它們是不可變的,只是JavaScript在引 ...
JavaScript中具有幾個簡單數據類型:數字number、字元串string、布爾值boolean、null值以及undefined值。除此之外其餘所有值(包括數組Array、函數Function,甚至正則表達式RegExp)都是對象。JavaScript是一門完全基於對象的語言,因此每次學習JavaScript的時候,就要摸摸自己的腦袋,暫時清空一下以前關於類的概念,尤其是要解決原型的關係問題的時候。
1. 對象的簡單介紹與一些註意事項
數字、字元串以及布爾值錶面是對象(因為當你聲明變數引用它們時,你會發現它們具有方法),但其實它們是不可變的,只是JavaScript在處理引用數字、字元串或者布爾值時,通過調用new Number()、new String()和new Boolean()構造器將其轉換為了數字、字元串或布爾對象,它自有的方法也是從這幾個構造函數的原型中繼承得到的。基本數據類型不可以被改變,因此在沒有指針再指向它時,它在記憶體中占用的資源自動被釋放,而對象卻永遠以引用的方式傳遞,改變對象中的值,也就改變了它在記憶體中的值。
註:理論上說,null值就是null值,不應該被檢測為對象,但實際上,由於JavaScript的設計失誤, typeof null === "object" 是一個事實。
因此在檢驗null值時,儘量要使用其他方法。假如放到if語句中,一般對象會返回true,而null值會返回false。這樣我們就可以使用 !null === true 進行檢測了。例如,要檢測一個剛獲取的DOM對象是否正常取值,我們應該使用如下的代碼:
1 var element = document.getElementById("elementID"); 2 if(element){} 3 // 或者if(!element){}
而不要使用:
1 var element = document.getElementById("elementID"); 2 if(typeof element !== "object") {} 3 // 或者if(typeof element === "object") {}
上面說到,因為 typeof null === "object" ,下麵這段代碼中,即使element獲取不正常(即值為null)時,if語句也會按照獲取正常的結果辦事。
2. 對象的屬性
對象存在的意義就是它可以有許多的屬性和方法幫助我們表達邏輯。對象的屬性可以為任意的值,可以是數字、字元串、布爾值、null值,也可以是對象或者是函數(當然函數本質上也是對象)。輸出一個屬性,如果它已經被定義,但是一個null值,就會對應輸出null,如果它甚至還未被定義,就會對應輸出undefined。
我們先用字面量定義一個對象,方便後面的測試:
1 var game = { 2 name: "Mini Warior", 3 id: 201907271234, 4 qualification: { 5 type: "test" 6 } 7 }
我們對對象屬性的操作一般來說就是CURD,最常用的就是修改更新和檢索取值。
修改更新一個對象的屬性,我們可以直接使用賦值語句。而一般檢索並獲取對象的屬性,有兩種方法:第一種,因為更緊湊可讀性更強而最為常用的一種: var gameName = game.name; 我們稱為(這裡有個點↘). 表示法;第二種,就像獲取數組對應下標的值一樣: var gameName = game["name"]; 。檢索獲取屬性值時,我們也要考慮到屬性不存在的情況,這時候我們可以巧用運算符填充預設值: var gameName = game.name || "Mini Warior"; 。這時候如果game.name獲取為null值或undefined值,gameName也會被賦值為你所希望的初始值,而不會影響接下來代碼的運行。如果我們嘗試從undefined的屬性中取值,例如 var gameQualiPlayer = game.qualification.player; ,JavaScript將會拋出一個“TypeError”的錯誤,我們也可以巧用&&運算符: var gameQualiPlayer = game.qualification && game.qualification.player; 避免錯誤,但結果仍然是取出一個undefined值。
處理一些不需要的屬性時,假如期望遍歷對象的所有屬性,我們就需要把對象方法過濾掉,這個時候我們會使用 typeof propertyName ==='function' 。
如果是要過濾掉原型上的屬性,我們通常使用的辦法是Object.prototype.hasOwnProperty()方法。這個方法會返回布爾值,值為填入的參數是否在當前的對象中。比較常用的用法是在使用for in語句遍歷對象時,for in語句預設會遍歷到原型鏈上的屬性。假如在開發過程中原型鏈上的屬性被其他人修改,而你不清楚,就會發生莫名的錯誤。沒有添加hasOwnProperty方法進行過濾時:
1 function Player(name, age, gender) { 2 this.name = name; 3 this.age = age; 4 this.gender = gender; 5 } 6 7 Player.prototype.getName = function() { 8 return this.name; 9 } 10 11 var player = new Player('MotherLyn', 3, 'male'); 12 13 var playerPropertyName = []; 14 var playerProperty = []; 15 16 for (var key in player){ 17 playerPropertyName.push(key); 18 playerProperty.push(player[key]); 19 }
列印發現,兩個數組中均存在getName相關內容。下麵使用Object.prototype.hasOwnProperty()過濾:
1 function Player(name, age, gender) { 2 this.name = name; 3 this.age = age; 4 this.gender = gender; 5 } 6 7 Player.prototype.getName = function() { 8 return this.name; 9 } 10 11 var player = new Player('MotherLyn', 3, 'male'); 12 13 var playerPropertyName = []; 14 var playerProperty = []; 15 16 for (var key in player){ 17 if(player.hasOwnProperty(key)){ 18 playerPropertyName.push(key); 19 playerProperty.push(player[key]); 20 } 21 }
這樣,在遍歷過程中,就不會把getName這個方法的鍵和值存到對應數組裡面。
對象的屬性有的可枚舉,有的不可枚舉。像我們上面這樣使用for in語句遍歷一個對象時,所有可枚舉的屬性或方法都會受到影響,因此我們提到可以使用typeof關鍵字或hasOwnProperty方法進行過濾。但我們知道,JavaScript中Array也是對象,我們建立數組,輸出它,會發現數組的下標是鍵,值是值,還有一個不可枚舉的length屬性(當然還有原型)。在這種情況下,我們使用for in語句就不會影響到length屬性。for in語句不僅容易遍歷到方法和原型屬性,還無法控制屬性名的順序,因此我們遍歷的最佳實踐應該是使用普通的for語句而不是for in語句(當然,當講到閉包時,我們也會發現for語句也並不是完美的,但至少它在大多數情況下都比for in遍歷要好)。
至於對象屬性的刪除,我們會使用到delete運算符,需要註意的一點就是它將不會觸及到原型鏈里的內容,但刪除此對象的屬性後,可能會讓原型鏈的屬性浮現:假設我們有一個player對象,它有一個屬性nickname: "Lyn",它的原型上也有一個屬性nickname: "Ben",經過 delete player.nickname; 後,輸出player.nickname的值為Ben。
對象幫助我們編寫可擴展、可重用、高質量的JavaScript庫。但當然,對象還有幾個重要的問題是原型鏈和對象的創建方法種類,它值得我們放到一篇新的博客中講述。
總結: ① 在JavaScript中,有五個基本類型,分別是:number、string、boolean、null和undefined,除此之外其餘全是對象。對於這五個基本類型,它本身不可修改,但在聲明變數引用它們時,JavaScript會自動調用對應的構造器將其轉化成對象,因此在使用者看來會有一種它們都是對象的錯覺。
② 熟悉對象屬性方法的聲明和取值方法。
③ 合理使用typeof關鍵字、hasOwnProperty方法等判斷是否正常取值,以及處理不正常取值得到的結果。