Vue裏面有個耳熟能詳的詞是Object.defineproperty,這篇文章就介紹一下這個屬性。函數
Object.defineProperty() 方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性, 並返回這個對象。
Object.defineProperty(obj, prop, descriptor)this
屬性描述符又可分爲數據描述符和存取描述符,能夠用getOwnPropertyDescriptors或者getOwnPropertyDescriptor獲取到屬性描述
數據描述符和存取描述符共有的屬性包括:code
configurable對象
當且僅當該屬性的 configurable 爲 true 時,該屬性描述符纔可以被改變,同時該屬性也能從對應的對象上被刪除,若是爲false,則不能刪除或修改writable, configurable, enumerable。默認爲 true。繼承
var animal = { name: 'cat' } console.log(Object.getOwnPropertyDescriptors(animal)) //name: {value: "cat", writable: true, enumerable: true, configurable: true} console.log(animal.name) //cat delete animal.name console.log(animal.name) //undefined Object.defineProperty(animal, 'name', { value: 'dog', configurable: false }) console.log(Object.getOwnPropertyDescriptors(animal)) //name: {value: "dog", writable: false, enumerable: false, configurable: false} console.log(animal.name) //dog delete animal.name console.log(animal.name) //dog
能夠看到,configurable默認屬性是true,設置爲false以後,delete對象的屬性將失效ip
須要注意的是,若是不是經過defineproperty定義的屬性,描述符默認值都是true;經過defineproperty定義的屬性,描述符默認是false
enumerableci
當且僅當該屬性的enumerable爲true時,該屬性纔可以出如今對象的枚舉屬性中(for...in, Object.keys())。默認爲 true。get
let animal = { name: 'cat' } for (let i in animal) { console.log(animal[i]) //cat } Object.defineProperty(animal, 'name', { enumerable: false }) for (let i in animal) { console.log(animal[i]) //無輸出 }
數據描述符其他屬性:it
該屬性對應的值。能夠是任何有效的 JavaScript 值(數值,對象,函數等)。默認爲 undefined。io
當且僅當該屬性的writable爲true時,value才能被賦值運算符改變。默認爲 true。
存取描述符其他屬性:
get
一個給屬性提供 getter 的方法,若是沒有 getter 則爲 undefined。當訪問該屬性時,該方法會被執行,方法執行時沒有參數傳入,可是會傳入this對象(因爲繼承關係,這裏的this並不必定是定義該屬性的對象)。
let animal = {} let name = 'cat' Object.defineProperty(animal, 'name', { value: 'cat', get: function () { return name } }) //報錯:Uncaught TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #<Object> let animal = {} let name = 'cat' Object.defineProperty(animal, 'name', { get: function () { return name } }) console.log(animal.name) //cat
若是一個描述符不具備value,writable,get 和 set 任意一個關鍵字,那麼它將被認爲是一個數據描述符。若是一個描述符同時有(value或writable)和(get或set)關鍵字,將會產生一個異常。
set
一個給屬性提供 setter 的方法,若是沒有 setter 則爲 undefined。當屬性值修改時,觸發執行該方法。該方法將接受惟一參數,即該屬性新的參數值。
let animal = {} let name = 'cat' Object.defineProperty(animal, 'name', { get: function () { return name }, set: function (val) { name = val } })
若是訪問者的屬性是被繼承的,它的 get 和set 方法會在子對象的屬性被訪問或者修改時被調用。若是這些方法用一個變量存值,該值會被全部對象共享。
能夠藉助中間值來解決
let animal = {} let name = 'cat' Object.defineProperty(animal, 'name', { get: function () { return this.stored_x }, set: function (val) { this.stored_x = val } })