js 响应式

65 阅读2分钟

1、Object.defineProperty

1)Object.defineProperty 的设计初中不是为了监听对象中属性变化的,而是为了定义访问属性描述符

2)Object.defineProperty 的缺点:

① 一次监听太多的时候,不是很友好;

② 新增、删除的时候,他是无能为力的;

③ 会修改原对象中的属性。

const obj = {
    name: "里斯",
    age: 16
};

/**
 * 监听某个属性
 */
/*
Object.defineProperty(obj, "name", {
    set(v) {
        console.log(v);
        console.log("监听到 set");
    },
    get() {
        console.log("监听到 get");
    }
});
*/

/**
 * 监听所有的属性
 */
Object.keys(obj).forEach(key => {
    console.log(key);
    let value = obj[key];
    Object.defineProperty(obj, key, {
        set(v) {
            console.log(`监听到属性 ${key},被 set 为 ${v}`);
            value = v;
        },
        get() {
            console.log(`监听到属性 ${key} get`);
            return value;
        }
    });
});


obj.name = "哈哈哈";

console.log(obj.name);

2、Proxy

在ES6中,新增了一个Proxy 类,这个类从名字就可以看出来,是用于帮助我们创建一个代理的,也就是说,如果我们希望监听一个对象的相关操作,那么我们可以先创建一个代理对象 ( Proxy 对象),之后对该对象的所有操作,都通过代理对象来完成,代理对象可以监听我们想要对原对象进行哪些操作。

1)对象的监听

代码太长,所以放的图片,如果图片加载失败,请到 github 查看

2)函数调用的监听

注:函数也是一个对象。

function fun() {
    console.log("哈哈哈");
}

const objProxy = new Proxy(fun, {
    /**
     * 拦截对函数的调用的捕获器
     * @param target target new Proxy 所代理的 obj(监听的对象)
     * @param thisArg 调用函数时绑定的 this 值
     * @param argArray 调用函数时传递的参数列表
     */
    apply(target, thisArg, argArray) {
        console.log("对 fun 函数进行了 apply 的调用。");
        // 调用原始函数,并在其结果前后添加一些内容
        target.apply(thisArg, argArray)
    },
    /**
     * 监听 class 时的捕获器
     * @param target target new Proxy 所代理的 obj(监听的对象)
     * @param argArray new fun() 时传入的参数,例:new fun(1, 2, ...rest)
     * @param newTarget 被调用的构造函数。在这里,newTarget 就是 objProxy 本身,因为 objProxy 是一个函数代理
     */
    construct(target, argArray, newTarget) {
        console.log("对 fun 函数进行了 construct 的调用。");
        return new target(...argArray)
    }
});

objProxy.apply();
new objProxy();