Proxy

# Proxy

# 基本使用

// const data = {
//   name: 'lamb',
//   age: 20
// }

const data = ["a", "b", "c"];

const proxyData = new Proxy(data, {
  get(target, key, receiver) {
    // 只处理本身(非原型的)属性
    const ownKeys = Reflect.ownKeys(target);
    if (ownKeys.includes(key)) {
      console.log("get", key); // 监听
    }

    const result = Reflect.get(target, key, receiver);
    return result; // 返回结果
  },
  set(target, key, val, receiver) {
    // 重复的数据,不处理
    if (val === target[key]) {
      return true;
    }

    const result = Reflect.set(target, key, val, receiver);
    console.log("set", key, val);
    // console.log('result', result) // true
    return result; // 是否设置成功
  },
  deleteProperty(target, key) {
    const result = Reflect.deleteProperty(target, key);
    console.log("delete property", key);
    // console.log('result', result) // true
    return result; // 是否删除成功
  },
});

# 实现响应式

proxy-observe.js

// 创建响应式
function reactive(target = {}) {
  if (typeof target !== "object" || target == null) {
    // 不是对象或数组,则返回
    return target;
  }

  // 代理配置
  const proxyConf = {
    get(target, key, receiver) {
      // 只处理本身(非原型的)属性
      const ownKeys = Reflect.ownKeys(target);
      if (ownKeys.includes(key)) {
        console.log("get", key); // 监听
      }

      const result = Reflect.get(target, key, receiver);

      // 深度监听
      // 性能如何提升的?
      /*
         不像defineProperty一上来就直接递归监听到底
         proxy仅在set时进行监听,并且仅仅监听到当前层级
      */
      return reactive(result);
    },
    set(target, key, val, receiver) {
      // 重复的数据,不处理
      if (val === target[key]) {
        return true;
      }

      const ownKeys = Reflect.ownKeys(target);
      if (ownKeys.includes(key)) {
        console.log("已有的 key", key);
      } else {
        console.log("新增的 key", key);
      }

      const result = Reflect.set(target, key, val, receiver);
      console.log("set", key, val);
      // console.log('result', result) // true
      return result; // 是否设置成功
    },
    deleteProperty(target, key) {
      const result = Reflect.deleteProperty(target, key);
      console.log("delete property", key);
      // console.log('result', result) // true
      return result; // 是否删除成功
    },
  };

  // 生成代理对象
  const observed = new Proxy(target, proxyConf);
  return observed;
}

// 测试数据
const data = {
  name: "zhangsan",
  age: 20,
  info: {
    city: "beijing",
    a: {
      b: {
        c: {
          d: {
            e: 100,
          },
        },
      },
    },
  },
};

const proxyData = reactive(data);

# 优点

  1. 深度监听,性能更好

  2. 可监听新增/删除属性

  3. 可监听数组变化

# 缺点

  1. Proxy 无法兼容所有浏览器,无法 polyfill

# Reflect

  1. 和 Proxy 能力一一对应

  2. 规范化、标准化、函数式

  3. 替代 Object 上的工具函数