在這篇文章裡,我們討論一下JavaScript中的物件、陣列以及錯誤處理。
1. 物件
物件是JavaScript中的一種基本型別,它內部包含一些屬性,我們可以對這些屬性進行增刪操作。
1.1 屬性
JavaScript中的值,有時會包括一些與其相關聯的值,這些相關聯的值,我們稱之為屬性。
訪問屬性
下面是一個非常簡單的示例:
1 var a = "this is test"; 2 print("type of a:" + typeof a); 3 print(a["length"]); 4 print(a.length); 5 6 //輸出結果 7 type of a:string 8 12 9 12
上述程式碼中,第3行和第4行的作用是一樣的,都是輸出a的長度。我們可以看到a是string型別的變數,它包含了一個名為length的屬性,這個屬性可以返回字串的長度。當需要呼叫屬性時,我們可以使用"變數名[屬性名稱]"的方式,也可以使用“變數名.屬性名稱”的方式。後者是前者的一個簡寫形式。
但是當屬性命名以數字等開頭時,我們只能以“[]”的形式來引用,例如:
1 var temp={"1":"a", "2":"b", "3":"c"}; 2 print(temp["1"]); 3 //print(temp.1);
上述程式碼最後一行如果不註釋掉,就會發生錯誤,因為“1”不符合JavaScript變數的命名規則。
在JavaScript中,物件由一個屬性集合構成,每個屬性的值還可以是一個屬性集合,以此類推。
刪除屬性
當我們試圖訪問一個不存在的屬性時,會返回undefined,我們可以通過delete操作來刪除。另外我們可以使用in操作來判斷屬性是否存在。
來看下面的示例:
1 var temp={"1":"a", "2":"b", "3":"c"}; 2 print(temp["1"]); 3 print("\'1\' in temp:" + ("1" in temp)); 4 delete temp["1"]; 5 print(temp["1"]); 6 print("\'1\' in temp:" + ("1" in temp)); 7 8 //輸出結果 9 a 10 '1' in temp:true 11 undefined 12 '1' in temp:false
可以看到,在使用了delete操作後,屬性已經被刪除了。
遍歷屬性
對於我們在程式中新增的屬性,是可以通過迴圈的方式進行遍歷的:
1 var temp={"1":"a", "2":"b", "3":"c"}; 2 for(var name in temp){ 3 print("temp["+name+"]="+temp[name]) 4 } 5 print(temp); 6 7 //輸出結果 8 temp[1]=a 9 temp[2]=b 10 temp[3]=c 11 [object Object]
非常有意思的是直接print物件時,輸出的是[object,object]。
1.2 修改物件
JavaScript中也有值型別和引用型別之分,我們可以通過修改物件中屬性的值來改變物件。
來看下面的示例:
1 var a={"start":10}; 2 var b=a; 3 var c={"start":10}; 4 print("a==b:" + (a==b)); 5 print("a==c:" + (a==c)); 6 print("a.start:" + a.start); 7 print("b.start:" + b.start); 8 print("c.start:" + c.start); 9 a.start=20; 10 print("a.start:" + a.start); 11 print("b.start:" + b.start); 12 print("c.start:" + c.start); 13 14 //輸出結果 15 a==b:true 16 a==c:false 17 a.start:10 18 b.start:10 19 c.start:10 20 a.start:20 21 b.start:20 22 c.start:10
2. 陣列
我們可以把物件看做是一個實體模型,它內部包含的資訊作為屬性存在。如果需要表示多個實體模型時,我們可以考慮使用集合。
我們使用"[]"來定義陣列,來看下面的示例:
1 function arrayTest(){ 2 var temp=["a","b","c"]; 3 temp.push("d"); 4 temp.push("e"); 5 for(var i = 0; i < temp.length; i++){ 6 print(temp[i]); 7 } 8 } 9 10 //輸出結果 11 a 12 b 13 c 14 d 15 e
我們有兩種方式向陣列中新增元素:1)初始化陣列時;2)使用push方法。
我們可以使用join方法將陣列轉換成一個字串,也可以使用split方法將一個字串轉換成字串陣列,如下:
1 var temp=["a","b","c"]; 2 temp.push("d"); 3 temp.push("e"); 4 print(temp.join(" ")); 5 print(temp); 6 var a="a b c d e"; 7 print(a.split(" ")); 8 9 //輸出結果 10 a b c d e 11 a,b,c,d,e 12 a,b,c,d,e
可以看到當我們直接print陣列時,它輸出了陣列中的每一個元素,但我們print物件時,它並沒有輸出物件中的屬性。
3. 錯誤處理
在編寫程式時發生的錯誤可以分為兩類:程式設計師錯誤和執行時錯誤。
對於程式設計師錯誤的處理策略,我們通常是期望程式儘快出錯,這樣可以弄清楚哪裡出了問題。同時我們也可以採取防禦性程式設計,例如新增輸入檢查。
對於執行時錯誤,我們應該儘量對錯誤進行處理,例如回滾,儘量避免程式崩潰。
3.1 處理錯誤的方式
在JavaScript中,我們有幾種方式可以用來處理錯誤。
返回特殊值
對於不符合業務邏輯的輸入,我們可以返回一個特殊值,例如undefined,這樣可以提示使用者方法的返回值是不正常的。
例如我們在JavaScript學習(1):基礎中提到的學習成績分類的示例,對於輸入的分數大於100或者小於0的情況,明顯不符合正常的業務,我們可以返回undefined。
這種錯誤處理方式的壞處:1)如何確定特殊的返回值,如果undefined在某種情況下也是正常業務的返回值,那麼我們如何處理?2)需要函式的呼叫方知道特殊的返回值,並且在每次呼叫的時候,對特殊返回值進行處理。
異常
我們可以通過throw、try...catch的方式來實現異常處理,下面是一個簡單示例:
1 function divide(a,b){ 2 if (b == 0) throw "can not divide 0"; 3 return a/b; 4 } 5 6 function errorTest(){ 7 try{ 8 divide(1,0); 9 } 10 catch(error){ 11 print("error occurs:" + error); 12 } 13 } 14 15 16 //輸出結果 17 error occurs:can not divide 0
我們可以自定義Error物件,這樣在catch時,可以更加細化的處理指定的異常。如下示例:
1 var zeroError = new Error("can not divide 0"); 2 3 function errorTest(){ 4 try{ 5 throw new Error("test"); 6 divide(1,1); 7 } 8 catch(error){ 9 if (error==zeroError){ 10 print("error occurs:" + error.message); 11 } 12 else{ 13 print(error.message); 14 } 15 } 16 } 17 18 //輸出結果 19 test
我們可以在catch後面新增finally語句,和Java一樣,可以在finally語句中釋放資源,恢復業務狀態等操作。