js中物件屬性的型別和屬性的特性
ES5中物件的屬性可以分為資料屬性和訪問器屬性
- 資料屬性
資料屬性包含以下4個特性:
[[configurable]]:表示屬性是否可以被delete,是否可以被重新修改,或者是否可以被修改成訪問器屬性
[[enumerable]]:是否可列舉,是否能通過for in 迴圈返回該屬性
[[writable]]: 是否可修改
[[value]]:屬性的資料值,預設是undefined
資料屬性可以通過字面量形式直接定義(包括obj.proper),或者通過Object.defineProperty(obj)來定義,如:
var obj = { _name: 'zyp', _age: 18, } Object.defineProperty(obj, 'like', { value: 'sleep' })
用Object.getOwnPropertyDescriptors(obj)可以獲取物件的所有屬性,包括屬性的特性。
var propers = Object.getOwnPropertyDescriptors(obj)
console.log('propers', propers)
輸出的結果見下圖,我們可以看到:通過字面量直接定義的資料屬性的[[configurable]]、[[enumerable]]、[[value]]三個特性值均預設為true;通過defineProperty()定義的資料屬性的[[configurable]]、[[enumerable]]、[[value]]三個特性值均預設為false。
2. 訪問器屬性(ie9+支援)
訪問器屬性包含以下4個特性:
[[configurable]]:表示屬性是否可以被delete,是否可以被重新修改,或者是否可以被修改成訪問器屬性
[[enumerable]]:是否可列舉,是否能通過for in 迴圈返回該屬性
[[set]]:設定屬性值是訪問的函式。預設是undefined
[[get]]:讀取屬性值是訪問的函式。預設是undefined
訪問器屬性只能通過Object.defineProperty(obj)來進行定義,如:
Object.defineProperty(obj, 'name', { get: function() { return this._name }, set: function(newVal) { this._name = newVal } }) var propers = Object.getOwnPropertyDescriptors(obj) console.log('propers', propers)
同樣,通過defineProperty()函式定義的訪問器屬性的[[configurable]]、[[enumerable]]兩個特性值均預設為false,如圖:
如果只定義了set特性或者只定義了get特性
Object.defineProperty(obj, 'age', {
set: function(newVal) {
this._age = newVal
}
})
var propers = Object.getOwnPropertyDescriptors(obj)
console.log('propers', propers)
var age = obj.age //得到的age值為undefined
因此,在非嚴格模式下,如果只定義了set特性,那麼獲取得到該訪問器屬性的值為undefined, 嚴格模式下會報錯(高程上是這麼說的,但是實際在chrome控制檯中用’use strict’並沒有丟擲錯誤)。
接下來對資料屬性和訪問器屬性共有的configurable特性進行研究:
針對obj中的資料屬性_age和_name
- _age屬性的configurable特性值為true,我們可以對其enumerable、writable、 value三個特性進行修改。
Object.defineProperty(obj, '_age', {
enumerable: false,
writable: false,
value: 19
})
var propers = Object.getOwnPropertyDescriptors(obj)
console.log('propers', propers)
也可以將其修改為訪問器屬性,或者直接delete該屬性,這裡只演示delete操作。
delete obj._age
var propers = Object.getOwnPropertyDescriptors(obj)
console.log('propers', propers)
- 我們將_name的configurable屬性為false後,我們只能將writable特性修改為false,不能修改其他特性,否則會報錯。
Object.defineProperty(obj, '_name', {
configurable: false
})
Object.defineProperty(obj, '_name', {
writable: false
}) //不報錯
Object.defineProperty(obj, '_name', {
value: 'zyp1'
})
也不能進行delete操作(無效)。
delete obj._name
注意:資料屬性的特性和訪問器屬性的特性不能同時存在於一個屬性中。
參考:JavaScript高階程式設計(第3版) 6.1.1