ECMAScript 中有兩種屬性:數據屬性和訪問器屬性。
1. 數據屬性
數據屬性包含一個數據值的位置。在這個位置能夠讀取和寫入值。數據屬性有4 個描述其行爲的特性。
[[Configurable]]:表示可否經過delete 刪除屬性從而從新定義屬性,可否修改屬性的特性,或者可否把屬性修改成訪問器屬性。像前面例子中那樣直接在對象上定義的屬性,它們的這個特性默認值爲true。
[[Enumerable]]:表示可否經過for-in 循環返回屬性。像前面例子中那樣直接在對象上定義的屬性,它們的這個特性默認值爲true。
[[Writable]]:表示可否修改屬性的值。像前面例子中那樣直接在對象上定義的屬性,它們的這個特性默認值爲true。
[[Value]]:包含這個屬性的數據值。讀取屬性值的時候,從這個位置讀;寫入屬性值的時候,
把新值保存在這個位置。這個特性的默認值爲undefined。函數
能夠屢次調用Object.defineProperty()方法修改同一個屬性,但在把configurable特性設置爲false 以後就會有限制了。this
在調用Object.defineProperty()方法時,若是不指定,configurable、enumerable 和writable 特性的默認值都是false。spa
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高級程序設計書上第六章的講解,最開始看的時候以爲奇奇怪怪的,不太懂這些看起來很底層的方法有什麼用。code
如今明白了,一個對象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函數呢?blog
由於,這樣增長了判斷,若是set值爲-1這樣不是正常年份的值,那麼就能夠報錯或者其餘的,不讓用戶設置成功。ip
同時也避免了用戶不當心設置錯了值的狀況。。get