Javascript Proxy

## JavaScript Proxy:赋予对象超能力的元编程利器(注释增强版)

/* 核心Proxy机制示例 */
const proxy = new Proxy(target, handler);
// target: 被代理的目标对象
// handler: 包含陷阱方法的配置对象

### 二、常用陷阱方法实战(带注释)

1. **安全属性访问**
```javascript
const validator = {
  /**
   * 属性访问拦截器
   * @param {object} target - 被代理的原始对象
   * @param {string|symbol} prop - 被访问的属性名
   */
  get(target, prop) {
    // 使用in运算符检查原型链
    return prop in target 
      ? target[prop] // 属性存在时返回正常值
      : `属性 ${prop} 不存在`; // 虚拟属性处理
  }
};

const person = { name: 'Alice' };
const proxy = new Proxy(person, validator);
console.log(proxy.age); // 触发get陷阱
  1. 数据验证拦截
const ageValidator = {
  /**
   * 属性设置拦截器
   * @param {number} value - 待设置的值
   * @throws {TypeError} 当类型不符合时
   * @throws {RangeError} 当数值越界时
   */
  set(target, prop, value) {
    if (prop === 'age') {
      // 类型检查
      if (!Number.isInteger(value)) {
        throw new TypeError('年龄需为整数');
      }
      
      // 边界检查
      if (value < 0) {
        throw new RangeError('年龄不能为负数');
      }
    }
    
    // 通过验证后设置属性
    target[prop] = value;
    
    // 严格模式下必须返回true
    return true; 
  }
};

const user = new Proxy({}, ageValidator);
user.age = 25;    // ✅ 合法操作
user.age = "25";  // ❌ 触发TypeError
  1. 函数调用监控
const logger = {
  /**
   * 函数调用拦截器
   * @param {Function} target - 被代理的原始函数
   * @param {*} thisArg - 函数调用时的this上下文
   * @param {Array} args - 参数数组
   */
  apply(target, thisArg, args) {
    // 记录调用日志
    console.log(`调用函数 ${target.name},参数:${args}`);
    
    // 执行原始函数并返回结果
    return target.apply(thisArg, args); 
  }
};

function sum(a, b) { return a + b; }
const loggedSum = new Proxy(sum, logger);
loggedSum(3, 4); // 输出日志并返回7

三、高级应用场景(带实现注释)

  1. 响应式系统核心
const reactive = (obj) => {
  return new Proxy(obj, {
    get(target, prop) {
      track(target, prop); // 依赖收集
      return Reflect.get(...arguments); // 使用Reflect保持默认行为
    },
    set(target, prop, value) {
      trigger(target, prop); // 触发更新
      return Reflect.set(...arguments); // 返回设置结果
    }
  });
};

// 简化的依赖管理实现
const dep = new Map(); // 存储依赖关系
function track(target, prop) {
  // 实际实现会记录正在运行的effect
  console.log(`追踪: ${target.constructor.name}.${prop}`);
}

function trigger(target, prop) {
  // 通知所有关联的观察者
  console.log(`触发更新: ${target.constructor.name}.${prop}`);
}
  1. 智能API缓存
/**
 * 创建带缓存的API代理
 * @param {Function} apiFunc - 原始API函数
 * @returns {Proxy} 带缓存功能的代理对象
 */
const createCachedApi = (apiFunc) => {
  const cache = new Map(); // 使用Map存储缓存数据
  
  return new Proxy(apiFunc, {
    apply(target, thisArg, args) {
      const key = JSON.stringify(args); // 参数序列化为缓存键
      
      if (cache.has(key)) {
        console.log('从缓存读取');
        return cache.get(key);
      }
      
      const result = target(...args); // 执行实际请求
      cache.set(key, result); // 缓存结果
      
      return result;
    }
  });
};

// 使用示例
const fetchData = (url) => fetch(url).then(r => r.json());
const cachedFetch = createCachedApi(fetchData);
  1. 虚拟属性扩展
const virtualProperties = {
  get(target, prop) {
    // 动态生成fullName属性
    if (prop === 'fullName') {
      return `${target.firstName} ${target.lastName}`; // 拼接姓名
    }
    
    // 其他属性保持默认行为
    return target[prop];
  }
};

const person = new Proxy(
  { firstName: 'John', lastName: 'Doe' },
  virtualProperties
);

console.log(person.fullName); // "John Doe"
console.log(person.firstName); // "John"

四、注意事项(增强说明)

  1. 性能优化策略
// 避免在热代码路径中使用复杂陷阱
const heavyProxy = new Proxy({}, {
  get(target, prop) {
    // ❌ 避免在频繁调用的get陷阱中进行复杂计算
    performHeavyCalculation();
    return Reflect.get(...arguments);
  }
});
  1. 安全撤销示例
// 创建可撤销代理
const {proxy, revoke} = Proxy.revocable({}, {});

proxy.name = 'test'; // ✅ 正常操作
revoke(); // 撤销代理
proxy.name; // ❌ 抛出TypeError
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王小玗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值