ECMAScript 中有兩種屬性:數據屬性和訪問器屬性。
1. 數據屬性
數據屬性包含一個數據值的位置。在這個位置可以讀取和寫入值。數據屬性有4 個描述其行為的特性。
[[Configurable]]:表示能否通過delete 刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改為訪問器屬性。像前面例子中那樣直接在對象上定義的屬性,它們的這個特性默認值為true。
[[Enumerable]]:表示能否通過for-in 循環返回屬性。像前面例子中那樣直接在對象上定義的屬性,它們的這個特性默認值為true。
[[Writable]]:表示能否修改屬性的值。像前面例子中那樣直接在對象上定義的屬性,它們的這個特性默認值為true。
[[Value]]:包含這個屬性的數據值。讀取屬性值的時候,從這個位置讀;寫入屬性值的時候,
把新值保存在這個位置。這個特性的默認值為undefined。
可以多次調用Object.defineProperty()方法修改同一個屬性,但在把configurable特性設置為false 之后就會有限制了。
在調用Object.defineProperty()方法時,如果不指定,configurable、enumerable 和writable 特性的默認值都是false。
2. 訪問器屬性
訪問器屬性不包含數據值;它們包含一對兒getter 和setter 函數(不過,這兩個函數都不是必需的)。
在讀取訪問器屬性時,會調用getter 函數,這個函數負責返回有效的值;在寫入訪問器屬性時,會調用setter 函數並傳入新值,這個函數負責決定如何處理數據。訪問器屬性有如下4 個特性。
[[Configurable]]:表示能否通過delete 刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改為數據屬性。對於直接在對象上定義的屬性,這個特性的默認值為true。
[[Enumerable]]:表示能否通過for-in 循環返回屬性。對於直接在對象上定義的屬性,這個特性的默認值為true。
[[Get]]:在讀取屬性時調用的函數。默認值為undefined。
[[Set]]:在寫入屬性時調用的函數。默認值為undefined。
var book = { _year: 2004, edition: 1 }; Object.defineProperty(book, "year", { get: function() { return this._year; }, set: function(newValue) { if (newValue > 2004) { this._year = newValue; this.edition += newValue - 2004; } } }); book.year = 2005; alert(book.edition); //2
以上都是摘自js高級程序設計書上第六章的講解,最開始看的時候覺得奇奇怪怪的,不太懂這些看起來很底層的方法有什么用。
現在明白了,一個對象book,有個屬性year,但是如果讓用戶隨便一個book.year=-1;這樣的話可不好啊,於是乎,book定義的year前面加了個_,表示是私有的,對於用戶來說也不會知道有這么個變量,用戶只會知道year,Object.defineProperty里面定義了“year”這個屬性,也就是說,如果用戶book.year,那么一般會返回對應的值,這里就會調用get函數,返回去的是_year值,用戶來看就是book.year返回了2004,實際上內部用了get函數返回的是_year值;如果用戶book.year=2017;那么實際上調用了set函數,將_year改成2017,這樣用戶再調用book.year就是2017了。
為什么非得加個get和set函數呢?
因為,這樣增加了判斷,如果set值為-1這樣不是正常年份的值,那么就可以報錯或者其他的,不讓用戶設置成功。
同時也避免了用戶不小心設置錯了值的情況。。
