5.8 屬性的訪問
生成的物件可以通過屬性來訪問。對於物件的引用可以使用點運算子(.)或中括號運算子([])來訪問其屬性。需要注意的是,在點運算子之後書寫的屬性名會被認為是識別符號,而中括號運算子內的則是被轉為字串值的式子。請看下面的例子:
var hzh1 = { x:3, y:4 }; console.log("輸出hzh物件的x屬性:"); console.log("hzh1.x = " + hzh1.x); // 屬性x console.log("hzh1[x] = " + hzh1['x']); // 屬性x var hzh2 = 'x'; console.log("hzh1[hzh2] = " + hzh1[hzh2]); // 屬性x(而非屬性key)
[Running] node "e:\HMV\JavaScript\JavaScript.js"
輸出hzh物件的x屬性:
hzh1.x = 3
hzh1[x] = 3
hzh1[hzh2] = 3
[Done] exited with code=0 in 0.181 seconds
不過,對於物件字面量的屬性名來說,下面這樣的識別符號或字元字面量形式的表示,都沒問題。請注意不要與上面的規則混淆。
var hzh1 = 'x';
var hzh2 = { hzh1:3 }; // 屬性hzh1(而非屬性x)
var hzh2 = { 'x':3 }; // 屬性x
這裡需要多提一句,屬性訪問的運算物件並不是變數,而是物件的引用。這一點,可以從以下直接 對物件字面量進行運算的示例中得到確認:
console.log("確認屬性訪問的運算物件是物件的引用:");
console.log({x:3, y:4}.x); // 屬性x
console.log({x:3, y:4}['x']); // 屬性x
[Running] node "e:\HMV\JavaScript\JavaScript.js"
確認屬性訪問的運算物件是物件的引用:
3
3
[Done] exited with code=0 in 0.183 seconds
現實中幾乎不會對物件字面量進行運算。不過當這種運算物件不是一個變數時,倒是常常會以方法鏈之類的形式出現。
5.8.1 屬性值的更新
在賦值表示式的左側書寫屬性訪問表示式能夠實現對屬性值的改寫。如果指定的是不存在的屬性名,則會新增該屬性。下面將不再使用右側或左側的說法,而改用屬性讀取,以及屬性寫入這樣的術語。
可以使用 delete 運算表示式來刪除屬性。這裡需要注意的是,很難區分不存在的屬性與屬性值為undefined 值的屬性。
5.8.2 點運算子與中括號運算子在使用上的區別
有時選擇用於訪問物件屬性的這兩個運算子只憑偏好。點運算子的表述較為簡潔,所以通常都會選用點運算子。不過,中括號運算子的通用性更高。
能使用點運算子的情況一定也可以使用中括號運算子,反之未必成立。但也無需因此全都使用中括號運算子。通常預設使用表述簡潔的點運算子,只有在不得不使用中括號運算子的情況下,才使用中括號運算子。
只能使用中括號運算子的情況分為以下幾種。
- 使用了不能作為識別符號的屬性名的情況。
- 將變數的值作為屬性名使用的情況。
- 將表示式的求值結果作為屬性名使用的情況。
包含數值或橫槓(-)的字串不能作為識別符號使用。無法作為識別符號使用的字串,不能用於點運算子的屬性名,且對於保留字,也有這樣的限制。不過,原本就不應該將保留字作為屬性名使用,所以這裡不再贅述。
像下面這樣,將含有橫槓的屬性名用於點運算子會引起錯誤。
// 含有橫槓的屬性名
var hzh = { 'huang-zihan':5 };
console.log(hzh.huang-zihan); // 將解釋為hzh.huang減去zihan,從而造成錯誤
[Running] node "e:\HMV\JavaScript\JavaScript.js"
e:\HMV\JavaScript\JavaScript.js:3
console.log(hzh.huang-zihan); // 將解釋為hzh.huang減去zihan,從而造成錯誤
^
ReferenceError: zihan is not defined
at Object.<anonymous> (e:\HMV\JavaScript\JavaScript.js:3:23)
at Module._compile (internal/modules/cjs/loader.js:999:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
at Module.load (internal/modules/cjs/loader.js:863:32)
at Function.Module._load (internal/modules/cjs/loader.js:708:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
at internal/main/run_main_module.js:17:47
[Done] exited with code=1 in 0.413 seconds
無法作為識別符號被使用的字串,仍可以在中括號運算子中使用。請看下面的例子,其中以字串值指定了一個屬性名。
// 含有橫槓的屬性名
var hzh = { 'huang-zihan':5 };
console.log(hzh['huang-zihan']); // 使用[]運算以字串值指定了一個屬性名。可以正常執行
[Running] node "e:\HMV\JavaScript\JavaScript.js"
5
[Done] exited with code=0 in 0.773 seconds
數值也是如此。陣列物件的屬性名都是數值。由於點運算子無法使用數值,因此只能使用中括號運算子。而且很多程式設計語言都是通過中括號運算子來訪問陣列的元素,所以可讀性也隨之提高。
下面的例子仍使用了之前的程式碼,用於展示將被變數的值作為屬性名使用的情況。
var hzh1 = { x:3, y:4 };
console.log("輸出hzh物件的x屬性:");
console.log("hzh1.x = " + hzh1.x); // 屬性x
console.log("hzh1[x] = " + hzh1['x']); // 屬性x
var hzh2 = 'x';
console.log("hzh1[hzh2] = " + hzh1[hzh2]); // 屬性x(而非屬性key)
[Running] node "e:\HMV\JavaScript\JavaScript.js"
輸出hzh物件的x屬性:
hzh1.x = 3
hzh1[x] = 3
hzh1[hzh2] = 3
[Done] exited with code=0 in 0.181 seconds
如果表示式的求值結果是字串,可以直接用中括號運算子通過該表示式指定屬性名。下面引用出自《JavaScript 語言精粹》一書的一個具有一定技巧性的例子。
這段程式碼會根據數值的符號而選擇呼叫不同的方法。方法呼叫一詞會讓人覺得要使用的是點運算子,不過事實上中括號運算子也能被呼叫。
// 引用自《JavaScript語言精粹》一書
// 僅讀取數值的整數部分的處理
Math[this < 0 ? 'ceiling' : 'floor'](this));
5.8.3 屬性的列舉
可以通過 for in 語句對屬性名進行列舉(程式碼清單 5.10)。通過在 for in 語句中使用中括號運算子,可以間接地實現對屬性值的列舉。使用 for each in 語句可以直接列舉屬性值。
程式碼清單 5.10 屬性的列舉
var hzh1 = { x:'黃子涵是帥哥!', y:'黃子涵是靚仔!', z:'黃子涵真聰明!' };
for(var key in hzh1) {
console.log('key = ', key); // 屬性名的列舉
console.log('val = ', hzh1[key]); // 屬性值的列舉
}
[Running] node "e:\HMV\JavaScript\JavaScript.js"
key = x
val = 黃子涵是帥哥!
key = y
val = 黃子涵是靚仔!
key = z
val = 黃子涵真聰明!
[Done] exited with code=0 in 0.262 seconds
屬性可以分為直接屬性以及繼承於原型的屬性。for in 語句和 for each in 語句都會列舉繼承於原型的屬性。