手写Object.defineProperty(),vue检测数组变化的代码

本文探讨了JavaScript中对象监听技术,如Observe函数实现的深度监听,并着重介绍了如何重写数组方法以实现实时数据响应。通过观察对象属性变化和数组操作,展示了如何在对象和数组的修改中保持数据同步。

1,对象监听

let obj = {
        a: {
          b: 1,
          c: 2,
        },
        d: 4,
      };
      observe(obj);
      obj.a.b = 3; //直接修改b的值 监听成功
      obj.a = 4; //把a赋值成基本类型 监听成功
      obj.d = 5; //直接修改d的值 监听成功
      obj.d = {
        //把d修改成对象 监听成功
        e: 8,
      };
      console.log(obj.d);
      //对对象进行观测
      function observe(target) {
        if (typeof target !== "object" || target === null) {
          return target;
        }
        //如果target为数组则改变原型指向,使用重写后的方法
        if (Array.isArray(target)) {
          target.__proto__ = arrProto;
        }
        //遍历每一个属性,进行监听
        for (let key in target) {
          defineProperty(target, key, target[key]);
        }
      }

      //监听函数
      function defineProperty(target, key, value) {
        //当value也为对象时进行递归深度监听
        observe(value);
        Object.defineProperty(target, key, {
          get() {
            return value; //依赖收集
          },
          set(newValue) {
            if (newValue !== value) {
              update(value, newValue); //通知相关依赖进行更新
              value = newValue;
              //当新值赋值为对象时, 对该对象进行监听
              observe(newValue);
            }
          },
        });
      }

      function update(oldValue, newValue) {
        console.log(`oldValue: ${oldValue}, newValue: ${newValue}`);
      }

2,数据响应式数组方法重写

 let arrPrototype = Array.prototype;
      // 该方法创建新对象,隐式原型原型指向arrPrototype,扩展新的方法时不会影响原型
      const arrProto = Object.create(arrPrototype);

      //重写方法的返回值
      ["push", "pop", "shift", "unshift", "splice", "sort", "reverse"].forEach(
        (methodName) => {
          // 缓冲原始数组的方法
          var original = arrayProto[method];
          // 利用Object.defineProperty对方法的执行进行改写
          def(arrayMethods, method, function mutator(val) {
            var args = [],
              len = arguments.length;
            while (len--) args[len] = arguments[len];
            // 执行原数组方法
            var result = original.apply(this, args);
            // 新增数组的方法push,unshift,splice可以帮我们更新数组中的新增一项
            var inserted;
            switch (method) {
              case "push":
              case "unshift":
                inserted = args;
                break;
              case "splice":
                inserted = args.slice(2);
                break;
            }
            //在此处进行通知
            return result;
          });
        }
      );

      //进行监听
      function def(obj, key, val, enumerable) {
        Object.defineProperty(obj, key, {
          value: val,
          enumerable: !!enumerable,
          writable: true,
          configurable: true,
        });
      }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值