数据监听

对象的监听

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);    这种写法也同样的
相关文章
相关标签/搜索