一、物件賦值的兩種方式
一是“=”賦值,一是Object.defineProperty方法,而當下流行框架中廣泛應用的雙向繫結和資料監聽等,就是利用的第二種方式,關於此方法不多講,可參考
developer.mozilla.org/zh-CN/docs/…
需要注意一點的是,
var bValue;
Object.defineProperty(o, "b", {
get : function(){
return bValue;
},
set : function(newValue){
bValue = newValue;
},
enumerable : true,
configurable : true
});
o.b = 38;複製程式碼
雖然其中set方法是這樣寫的,
set : function(newValue){
bValue = newValue;
},複製程式碼
所以此處的a.b=arg不同於一般的. 語法,而是已經觸發了setter了
二、為什麼Object.defineProperty能實現雙向繫結和資料監聽呢
因為Object.defineProperty方法裡有getter和setter函式對,你可以把它理解為一個可以觸發的函式,觸發事件就是setter對應的屬性被改變
eg:
var bValue = 38;
Object.defineProperty(o, 'b', {
get: function() { return bValue; },
set: function(newValue) {
bValue = newValue;
you can do something, like update the new data to virual dom!
},
enumerable: true,
configurable: true
});
o.b; // 38
//屬性”b”被設定到物件o上,並且值為38。
//現在o.b的值指向bValue變數,除非o.b被重新定義
複製程式碼
三、框架裡的具體做法是怎樣的呢?
一句話描述,就是把在data裡註冊的所有屬性都新增上對應的getter和setter函式對。
形象點,可以參照下面的方法:使用defineProperty方法封裝一個監聽屬性變動的函式。
var object = {
name:'liwudi',
age:34
}
function changeIt(object) {
function descripterFun(value) {
return {
enumerable: true,
get: function () {
console.log('get it');
return value;
},
set: function (newvalue) {
console.log('set it');
value = newvalue;
}
}
}
for(var i in object){
Object.defineProperty(object, i, descripterFun(object[i]))
}
}
changeIt(object);
console.log(object.name);
object.name = '我是中國人';
console.log(object);
複製程式碼
當然,真正要解決的問題遠比上述複雜,比如更深層次的屬性要利用到遞迴方法等等。
參考資料: