前置知识: JavaScript

Proxy与Reflect

1 minAdvanced2026/6/14

元编程:代理与反射API

1. Proxy 概述

const target = { name: 'Alice', age: 25 };
const handler = {
  get(target, prop) {
    console.log(`读取属性: ${prop}`);
    return target[prop];
  },
  set(target, prop, value) {
    console.log(`设置属性: ${prop} = ${value}`);
    target[prop] = value;
    return true;
  },
};

const proxy = new Proxy(target, handler);
console.log(proxy.name); // 读取属性: name → Alice
proxy.age = 30; // 设置属性: age = 30

2. 可拦截的操作

陷阱拦截操作
getproxy[prop]
setproxy[prop] = val
hasprop in proxy
deletePropertydelete proxy[prop]
ownKeysObject.keys()
applyproxy(...args)
constructnew proxy(...args)

3. Reflect API

const handler = {
  get(target, prop, receiver) {
    console.log(`get ${prop}`);
    return Reflect.get(target, prop, receiver);
  },
  set(target, prop, value, receiver) {
    console.log(`set ${prop}`);
    return Reflect.set(target, prop, value, receiver);
  },
};

4. 实际应用

4.1 响应式数据绑定

function reactive(obj, onChange) {
  return new Proxy(obj, {
    set(target, prop, value) {
      const old = target[prop];
      target[prop] = value;
      if (old !== value) onChange(prop, value, old);
      return true;
    },
    get(target, prop) {
      const value = target[prop];
      if (value && typeof value === 'object') {
        return reactive(value, onChange);
      }
      return value;
    },
  });
}

4.2 私有属性保护

function privatize(obj) {
  return new Proxy(obj, {
    get(target, prop) {
      if (prop.startsWith('_')) throw new Error(`私有属性 ${prop}`);
      return Reflect.get(target, prop);
    },
    has(target, prop) {
      if (prop.startsWith('_')) return false;
      return Reflect.has(target, prop);
    },
    ownKeys(target) {
      return Reflect.ownKeys(target).filter((k) => !k.startsWith('_'));
    },
  });
}

5. 可撤销代理

const { proxy, revoke } = Proxy.revocable(target, handler);
revoke(); // 撤销后任何操作都会抛出 TypeError