Object.defineProperty() 方法會直接在一個對象上定義一個新屬性,或在修改一個對象的現有屬性,並返回這個對象(即第一個參數obj)vue
語法:函數
Object.defineProperty(obj , prop , descriptor)測試
//obj:要在其上定義屬性的對象 //prop:要定義或修改的屬性的名稱 //descriptor:將被定義或修改的屬性描述符
vue.js就是經過Object.defineProperty實現雙向綁定spa
給對象的屬性添加特性描述,目前提供兩種形式:數據描述和存取器描述雙向綁定
數據描述code
當修改或定義對象的某個屬性的時候,給這個屬性添加一些特性對象
value: 設置屬性的值
writable: 值是否能夠重寫。true | false
enumerable: 目標屬性是否能夠被枚舉。true | false
configurable: 目標屬性是否能夠被刪除或是否能夠再次修改特性 true | falseblog
value:屬性對應的值,能夠是任意類型的值,默認爲undefinedip
let obj = {} //第一種狀況:不設置value屬性 Object.defineProperty(obj,"newKey",{ }); console.log( obj.newKey ); //undefined ------------------------------ //第二種狀況:設置value屬性 Object.defineProperty(obj,"newKey",{ value:"hello" }); console.log( obj.newKey ); //hello
writable:屬性的值是否能夠被重寫,默認爲false,設置爲true能夠被重寫ci
let Person = {}; Object.defineProperty(Person,'city',{ city:'倫敦' //writable默認爲false,不能改變屬性值 }) Person.city = '巴黎'; console.log(Person.city);//undefined
let Person = {}; Object.defineProperty(Person,'city',{ city:'倫敦', writable:true }) Person.city = '巴黎'; console.log(Person.city);//巴黎
enumerable:此屬性是否能夠被枚舉
設置爲true能夠被枚舉;設置爲false,不能被枚舉(默認false)
var obj = {} //第一種狀況:enumerable設置爲false,不能被枚舉。 Object.defineProperty(obj,"newKey",{ value:"hello", writable:false, enumerable:false }); //枚舉對象的屬性 for( var attr in obj ){ console.log( attr ); } //第二種狀況:enumerable設置爲true,能夠被枚舉。 Object.defineProperty(obj,"newKey",{ value:"hello", writable:false, enumerable:true }); //枚舉對象的屬性 for( var attr in obj ){ console.log( attr ); //newKey }
configurable:是否能夠刪除目標屬性或是否能夠再次修改屬性的特性
設置true能夠被刪除或能夠從新設置特性,false不能設置
這個屬性起到的做用
目標屬性是否能夠使用delete刪除
目標屬性是否能夠再次設置特性
//-----------------測試目標屬性是否能被刪除------------------------ var obj = {} //第一種狀況:configurable設置爲false,不能被刪除。 Object.defineProperty(obj,"newKey",{ value:"hello", writable:false, enumerable:false, configurable:false }); //刪除屬性 delete obj.newKey; console.log( obj.newKey ); //hello //第二種狀況:configurable設置爲true,能夠被刪除。 Object.defineProperty(obj,"newKey",{ value:"hello", writable:false, enumerable:false, configurable:true }); //刪除屬性 delete obj.newKey; console.log( obj.newKey ); //undefined
//-----------------測試是否能夠再次修改特性------------------------ var obj = {} //第一種狀況:configurable設置爲false,不能再次修改特性。 Object.defineProperty(obj,"newKey",{ value:"hello", writable:false, enumerable:false, configurable:false }); //從新修改特性 Object.defineProperty(obj,"newKey",{ value:"hello", writable:true, enumerable:true, configurable:true }); console.log( obj.newKey ); //報錯:Uncaught TypeError: Cannot redefine property: newKey //第二種狀況:configurable設置爲true,能夠再次修改特性。 Object.defineProperty(obj,"newKey",{ value:"hello", writable:false, enumerable:false, configurable:true }); //從新修改特性 Object.defineProperty(obj,"newKey",{ value:"hello", writable:true, enumerable:true, configurable:true }); console.log( obj.newKey ); //hello
一旦使用Object.defineProperty給對象添加屬性,那麼若是不設置屬性的特性,那麼configurable、enumerable、writable這些值都爲默認的false
當使用存取器描述屬性的特性的時候,容許設置如下特性屬性
當設置或獲取對象的某個屬性的值的時候,能夠提供getter/setter方法,沒有的話則爲undefined
getter 是一種得到屬性值的方法
setter是一種設置屬性值的方法
注意:當使用了getter或setter方法,不容許使用writable和value這兩個屬性
var obj = {}; var initValue = 'hello'; Object.defineProperty(obj,"newKey",{ get:function (){ //當獲取值的時候觸發的函數 return initValue; }, set:function (value){ //當設置值的時候觸發的函數,設置的新值經過參數value拿到 initValue = value; } }); //獲取值 console.log( obj.newKey ); //hello //設置值 obj.newKey = 'change value'; console.log( obj.newKey ); //change value
get或set不是必須成對出現,任寫其一就能夠。若是不設置方法,則get和set的默認值爲undefined
let obj = { num:4 }; let n = 2; Object.defineProperty(obj,'num',{ get:function(){ //取 obj.num 屬性時會觸發 get 方法 /*數據劫持*/ //當你獲取這個屬性的時候,會調用 n += 2; return n; }, set(val){ //給 obj.num 賦值時會觸發 set 方法 //val 是給 obj.num 賦值時的那個值 } }); console.log(obj.num < 5 && obj.num > 5);//true /*num即小於5,又大於,就是應爲,第一次判斷obj.num時num=(n+=2)=4,符合了第一個條件,此時的n=4。 讀到第二個判斷的時候,再次觸發函數,此時n+=以後爲6,又符合了第二個判斷條件,因此出現了true*/