Skip to content

Proxy 基本使用

回顾 Object.defineProperty 缺点

  • 深度监听,需要递归到底,一次性计算量大
  • 无法监听新增属性/删除属性(Vue.set Vue.delete)
  • 无法原生监听数组,需要特殊处理

Proxy 基本使用

js
// const data = {
//     name: 'zhangsan',
//     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);
    return result; // 是否设置成功
  },
  deleteProperty(target, key) {
    const result = Reflect.deleteProperty(target, key);
    console.log('delete property', key);
    console.log('result', result);
    return result; // 是否删除成功
  },
});
// proxyData.age
// // get age
//
// proxyData.age = 30
// // set age 30
// // result true
//
// delete proxyData.age
// // delete property age
// // result true
// proxyData.push('d')
// get push
// get length
// set 3 d
// result true
// set length 4
// result true
// 改进后
proxyData.push('d');
// get length
// set 3 d
// result true

Reflect 作用

  • 和 Proxy 能力一一对应
  • 规范化,标准化,函数化
  • 替代掉 Object 上的工具函数
js
const obj = { a: 100, b: 200 };
// 判断 a 在 obj 中的方法
console.log('a' in obj); // true
// 看起来更舒服
console.log(Reflect.has(obj, 'a')); // true
// 删除数据
console.log(delete obj.a); // true
console.log(Reflect.deleteProperty(obj, 'b')); // true
obj.a = 300;
obj.b = 400;
// 可以替换 Object 函数
console.log(Object.getOwnPropertyNames(obj)); // ["a", "b"]
console.log(Reflect.ownKeys(obj)); // ["a", "b"]

基于 MIT 许可发布