數據監聽

對象的監聽

es5Object.defineProperty是關鍵,一個已經定義好的對象,咱們能夠利用Object.defineProperty方法重寫它的屬性,添加get,set方法。數組

var obj = {
    name:"小明",
    age:18,
    say(){
        return "hello";
    }
}

for(let key in obj){
    let value = obj[key];  //利用閉包,存值
    Object.defineProperty(obj,key,{
        get(){
             return value;
        },
        set(val){
            console.log('改變了');
            value = val;
        },
    })
}

get,set回調裏能夠塞入咱們想要的操做。固然,上述代碼若是要嚴謹點的話,還應當區分是否監聽原型鏈上的屬性。能夠用hasOwnProperty方法或者Object.keys()方法排除原型鏈上的屬性。閉包

數組的監聽

由於種種歷史緣由,數組類型是無法用上面的方法進行監聽的,並且由於種種歷史緣由和實現方式的緣故,數組裏的元素改變是無法直接監聽到的,(好比 arr[3] = 9),因此只能退而求其次監聽數組的方法
實現思路很簡單,在Array和須要監聽的數組之間多構造一個數組對象,將監聽數組的原型__proto__指向構造的數組對象便可,構造的數組對象天然能夠覆寫數組方法,並添加本身的操做。app

var overRideArr = [];   //構造的數組對象
overRideArr['push'] = function(){
    console.log("監聽操做");
    return [].push.apply(this,arguments)
} 

var arr = ['a','b','c']; //  待監聽的數組
arr.__proto__ = overRideArr;  //改變原型指向

爲何要使用__proto__而不是建立一個繼承Array的類,並在其內部改寫對應方法呢?
由於除了 new Array(),別的方式沒法返回數組類型,即便構造了一個類,new 出來的也是會是個對象。因此經過改變實例的原型指向,是目前監聽數組最實用的方式。
哈?你說別的方式?固然就是直接覆寫某個實例數組了,好比這樣:ide

var arr = ['a','b','c']; //  待監聽的數組
arr['push'] = function(){
    console.log("監聽操做");
    return [].push.apply(this,arguments)
}

這種方法只有不支持__proto__屬性的時候纔會用,遠沒有使用__proto__方便。this

另外若是你真的很喜歡new的方式,其實能夠包裝一下,弄個形式,可是內裏仍是上面的代碼。es5

function  OverArr(arr){
    arr.__proto__ = overRideArr;
    return arr;
}

var arr2 = ['a','b','c']; //  待監聽的數組
arr2 = new OverArr(arr2);
//arr2 = OverArr(arr2);    這種寫法也同樣的
相關文章
相關標籤/搜索