一、Object.defineProperty的作用
用來給對象新增屬性,和修改對象中的屬性。
二、JS對象中的描述符
js對象中兩種屬性描述符:數據描述符和存取描述符(訪問描述符)。
注意事項:
1、數據描述符和存取描述符都具備configurable、enumerable屬性。
2、描述符不具備value,writetable,set和get任意一個關鍵字都被認作一個數據描述符。
3、(value或writetable)和(get和set)不能同時存在,然后只要定義了set和get或其中一個都是一個存取描述符(描述符只能是其中一種)。
三、Object.defineProperty的使用
var o = {}; // 創建一個新對象 // 在對象中添加一個屬性與數據描述符的示例 Object.defineProperty(o, "a", { value : 37, writable : true, enumerable : true, configurable : true }); // 對象o擁有了屬性a,值為37 // 在對象中添加一個屬性與存取描述符的示例 var bValue; Object.defineProperty(o, "b", { get : function(){ return bValue; }, set : function(newValue){ bValue = newValue; }, enumerable : true, configurable : true }); o.b = 38; // 對象o擁有了屬性b,值為38
1、writable、enumerable、configurable為false的情況
wirtable:變量不可再被重新賦值
enumerable: 變量不能在遍歷器例如for...in和Object.keys()中被讀取出來,不可被遍歷
configurable:變量不可配置,定義為false之后,不能再為該變量定義配置否則報錯。變量被刪除(delete)、修改都會無效。
2、如果對象的屬性是存取描述符,只會調用定義了的set和get(configurable、enumrable)
在給一個對象屬性做賦值操作,在讀取屬性值時,這個賦值操作賦值的值會被忽略,會去調用定義的get方法的值
function Archiver() { var temperature = null; var archive = []; Object.defineProperty(this, 'temperature', { set: function(value) { temperature = value; archive.push({ val: temperature }); } }); this.getArchive = function() { return archive; }; } var arc = new Archiver(); arc.temperature = "67" console.log(arc.temperature); // undefined arc.temperature = 11; arc.temperature = 13; arc.getArchive(); // [{ val: 11 }, { val: 13 }]
四、關於給對象定義set/get方法
vue中可以在computed中給變量定義get/set方法(https://cn.vuejs.org/v2/guide/computed.html),結合v-model雙向數據綁定變量有很多的用處,比如官網的名字的名和姓的拼接。在子組件中我們想要修改父組件傳來的值並及時在dom中渲染的時候。
computed中給變量定義set/get方法並不是vue中特有的方法,es5中支持了Object.defineProperty,在Object.defineProperty可以給對象的屬性設置為訪問描述符類型,定義set/get方法。我們除了通過這個方法給屬性定義set/get ,還可以通過對象文字語法來定義。
var myObject = { get a() { return 2 } } myObject.a = 3 console.log(myObject.a)//2 console.log(myObject.b)//undefined
參考資料:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
http://imweb.io/topic/56d40adc0848801a4ba198ce