JavaScript 核心觀念(25)-物件-未定義的物件屬性預設值

前言

接下來講講未定義的物件屬性與 undefined 的關連性吧。

未定義的物件屬性預設值

首先 undefined 與未定義的物件屬性是有非常大的關係,首先先來看以下範例是一個常見的物件實字

1
2
3
var obj = {
name: 'Ray',
}

當若我們要取得 objname 的話,我們可以使用點運算子或是中括號的方式取得 name

1
2
obj.name; // Ray
obj['name']; // Ray

但是如果我們點運算子後方帶上的是一個不存在的屬性的話,那麼會發生什麼事情

1
obj.status; // undefined

因此我們這邊可以知道一件事情,若輸入的不存在的屬性就會出現 undefined,但是如果輸入到第三層會發生什麼事情呢?也會是 undefined 嗎?

1
obj.status.name; // VM66:1 Uncaught TypeError: Cannot read property 'name' of undefined

這時候或許你會感到疑惑為什麼不是 undefined 呢?以錯誤訊息來講他是在說「你無法讀取 undefinedname 屬性」,試著回頭思考一下一開始我們知道 obj.status 會出現 undefined,因此問題就是出在第二層未定義的物件屬性上。

那麼問題是出在哪呢?首先這問題最主要與運算子的優先性及相依性有一定關係,我們在前面章節知道,若運算子在同一行有相同優先性的運算子,那麼就會改判斷相依性,在這邊點運算子的相依性是由左至右,因此左邊會優先取得物件屬性

1
obj.status; // undefined

接下來才會執行後面的 status.name,但是在前面我們已經知道 obj.status 執行後的結果是 undefined,因此實際的運作結果就會像這樣

1
undefined.name;

這也就是為什麼會出現 VM66:1 Uncaught TypeError: Cannot read property 'name' of undefined 的錯誤原因,其中還有一個重點是原始型別是不允許有自己的屬性,因此就算你針對 undefined 是無法新增成功的,所以上面的錯誤訊息意思是「你無法針對 undefined 增加一個 name 屬性。」

1
undefined.name = 'qq123' // Uncaught TypeError: Cannot set property 'name' of undefined

但是其他原始型別在錯誤上可能會有一點不同。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
null.name = 'qq123'; // VM309:1 Uncaught TypeError: Cannot set property 'name' of null

// Number
123.name = 'qq123'; // Uncaught SyntaxError: Invalid or unexpected token,這個錯是因為小數點被誤會成浮點數,因此這邊改用變數方式
var a = 123;
a.name = 'qq123';
a.name; // undefined

// String
'123'.name = 'qq123'; // 雖然不會出現錯誤,但實際上還是無法新增
'123'.name; // undefined

// Boolean
true.name='qq123'; // 雖然不會出現錯誤,但實際上還是無法新增
true.name; // undefined

而要解決這個問題的方法有兩種,一種是預先定義物件屬性

1
2
3
4
5
var obj = {
name: 'Ray',
status: {},
}
obj.status.name; // undefined

那麼另一種方式則是有可能我們在寫程式時,無法確定程式碼結構,但我們可以透過賦予方式解決

1
2
3
4
5
6
7
var obj = {
name: 'Ray',
}

obj.status = {};

obj.status.name; // undefined

另外這邊還有一件很特別的事情,如果你直接在瀏覽器上輸入 console.log(a); 是會出現 ReferenceError: a is not defined,這是因為這個 a 並不存在所導致,但是如果你輸入的是 console.log(window.a);,那麼你會發現竟然出現 undefined

1
2
console.log(a); // ReferenceError: a is not defined
console.log(window.a); // undefined

除此之外你還可以發現一件事情就是,當發生錯誤之後,程式碼就會立刻中斷不會往後執行。

而這兩者的差異在於物件取值時,有一個保護機制,而這個保護機制最主要是避免存取到一個不存在的屬性而導致 JavaScript 發生錯誤而中斷程式碼的運作唷。

參考文獻

0%