前言
Object.defineProperty是ES5中的方法,它可以直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性, 並返回這個對象。vue.js正式利用這種方法實現數據的雙向綁定,以達到響應式的目的。
1、語法
Object.defineProperty(object, propertyname, descriptor) //參數(3個且必須)
2、參數詳解
3.1、object:要在其上添加或修改屬性的對象。
3.2、propertyname:一個包含屬性名稱的字符串。就是需要定義的屬性和方法。
3.3、descriptor:可以包含以下屬性,默認情況下, writable, enumerable,configurable值為false
value:屬性的值
writable:如果為false,屬性的值就不能被重寫,只能為只讀了。
enumerable:是否能枚舉,也就是否能在for...in循環中遍歷出來或在Object.keys中列舉出來。
configurable:如果為false,就不能再設置他的(value,writable,configurable)。
還有兩個方法 (雙向數據綁定正是利用了這兩個方法,即訪問器 )get() 和 set()
3、看看栗子
var a= {}
Object.defineProperty(a,"b",{
value:111
})
console.log(a.b);//111
就是給a對象添加b屬性,並返回a對象;
再比如:把描述設置為不可寫;

4、訪問器 set和get
set();一旦屬性被重新賦值,此方法被自動調用。
get();一旦屬性被訪問讀取,此方法被自動調用。
不能同時設置訪問器 (get 和 set) 和 wriable 或 value,否則會錯。
var a= {}
Object.defineProperty(a,"b",{
set:function(val){
console.log("賦值時候調用我,我的新值是"+ val)
},
get:function(){
console.log("取值的時候調用我")
return 123
}
})
a.b =520 // 賦值時候調用我,我的新值是520
console.log(a.b) // 取值的時候調用我, 返回我設置123,不是開始設置的520
5、簡單雙向數據綁定
給對象a定義新的屬性b,並且定義屬性b的get和set方法,當a.b的時候會調用b屬性的get方法,給b屬性賦值的時候,會調用set方法,這就是修改數據的時候,視圖會自動更新的關鍵.(只能兼容IE8以上的瀏覽器,vue也是如此!)。
<label>輸入:</label><input type="text" id="demo1"><br/>
<label>輸出:</label> <input type="textarea" id="demo2"></input>
<script>
var a={};
var output=[];
Object.defineProperty(a,'b',{ //給a對象添加b屬性
set:function(val){
output['b']=val;
},
get:function(){
return output['b'];
}
})
var demo1=document.querySelector('#demo1');
var demo2=document.querySelector('#demo2');
demo1.onkeyup=function(){
a.b=demo1.value;//給a對象添加b屬性時候,觸發了a的set方法,此時#demo1的value值賦值給output['b']。
demo2.value=output['b'];
}
</script>

6、再看看Object.defineProperty實踐例子
直接在原型上添加一個不可遍歷的方法extend(),該方法可以把新對象賦值給舊對象;
Object.defineProperty(Object.prototype, 'extend',{
value : function(def, opt) {
for(var key in opt){
def[key] = opt[key];
}
return def;
},
writable: true,
enumerable : false
});
function func(options){
let def = {
payType: 'wechat',
buyType: -1,
isCard: false,
toUid: -1,
couponId: -1
};
let opt = extend(def, options);
this.isCardPay = opt.isCard;
this.payType = opt.payType;
.......
}
//使用
fuc({
payType: 'ali',
buyType: 2,
isCard: true,
toUid: 123456,
couponId: 667890
})
7、vue怎么實現數據雙向綁定?
vue.js 則是采用數據劫持結合發布者-訂閱者模式的方式,通過Object.defineProperty()來劫持各個屬性的setter,getter,在數據變動時發布消息給訂閱者,觸發相應的監聽回調。
