前言:這年頭全部用過vue的人都知道get,set,Object.defineProperty,可聽到屬性描述符卻有點懵。另外實際使用的場景有哪些,又有哪些坑可能不少人並不清楚,所以打算分兩篇文章,一篇講基礎知識,另外一篇講實際應用中的坑。vue
下面這麼個對象就是完整的屬性描述符。json
{ configurable: false, enumberable: false, value: 'value', writable: false, get: function() { console.log('get') }, set: function(val) { console.log('set') } }
固然正常狀況下你不會看到完整的屬性描述符。它的每一個屬性都是可選的。當一個屬性描述符沒有沒有get和set時,它是個數據描述符。當它沒有value和writable時,它是個存取描述符。若是一個描述符同時有(value或writable)和(get或set)關鍵字,將會產生一個異常。函數
描述符可同時具備的鍵值this
PropertyDescriptor | configurable | enumerable | value | writable | get | set |
---|---|---|---|---|---|---|
數據描述符 | Yes | Yes | Yes | Yes | No | No |
存取描述符 | Yes | Yes | No | No | Yes | Yes |
configurable
當且僅當該屬性的 configurable 爲 true 時,該屬性描述符
纔可以被改變,同時該屬性也能從對應的對象上被刪除。spa
enumerable
當且僅當該屬性的enumerable
爲true
時,該屬性纔可以出如今對象的枚舉屬性中。3d
value
該屬性對應的值。能夠是任何有效的 JavaScript 值(數值,對象,函數等)。code
writable
當且僅當該屬性的writable
爲true
時,value
才能被賦值運算符改變。對象
get
一個給屬性提供 getter 的方法,若是沒有 getter 則爲 undefined
。當訪問該屬性時,該方法會被執行,方法執行時沒有參數傳入,可是會傳入this
對象(因爲繼承關係,這裏的this
並不必定是定義該屬性的對象)。blog
set
一個給屬性提供 setter 的方法,若是沒有 setter 則爲 undefined
。當屬性值修改時,觸發執行該方法。該方法將接受惟一參數,即該屬性新的參數值。繼承
以上的定義和解釋來自於mdn,可是刪除了默認值的說明。默認值分兩種語境,一個是我沒有設置屬性描述符時,就去取它;另外一種是我設置屬性描述符,可是我省略了部分屬性。mdn上的默認值是後者。
Object.getOwnPropertyDescriptor
和Object.getOwnPropertyDescriptors
,二者模式差很少,懂一個就懂另外一個了。
可見其中writable、enumerable、configurable默認是true
Object.defineProperty
和Object.defineProperties
,一樣一個就懂另外一個了。
咱們分別設置get和value,而後再獲取屬性描述符看看區別
get:
value:
能夠看到,當我設置了屬性描述符後writable、enumerable、configurable默認是false。
enumerable爲false時
而且細心的同窗發現了,對象的這個屬性名的顏色有點不同。不過此時咱們先忽略這個顏色的區別。
咱們將它轉爲json字符串,發現沒有age和address。嗯,這就是由於enumerable設置成了false,使得它被轉爲字符串的過程當中沒法遍歷到這兩個屬性。咱們能夠將enumerable設置成true再試一下。
configurable爲false時
由於缺省的configurable默認爲false,當咱們再次設置時就報錯了。此時就陷入了無解的狀態,所以咱們平時開發中須要設置屬性描述符時,最好不要缺省enumerable和configurable。
咱們從頭來一次:
關於屬性描述符,我想你們應該都有一個大體的印象了,對於get和set我在後面實際應用中再解釋吧~