全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-16 10 分钟 ✍️ juanwangdev

JavaScript 代理与反射(Proxy/Reflect)

Proxy 用于拦截对象操作,Reflect 提供对应的反射方法,两者配合实现元编程。

Proxy 基础

JavaScript
const target = { name: 'Alice', age: 25 };

const proxy = new Proxy(target, {
  get(obj, prop) {
    console.log(`读取属性: ${prop}`);
    return obj[prop];
  },
  set(obj, prop, value) {
    console.log(`设置属性: ${prop} = ${value}`);
    obj[prop] = value;
    return true;
  }
});

proxy.name;      // 读取属性: name
proxy.age = 26;  // 设置属性: age = 26

拦截操作

拦截方法触发操作
get读取属性 proxy.key
set设置属性 proxy.key = value
hasin 操作符 key in proxy
deletePropertydelete proxy.key
ownKeysObject.keys(proxy)
apply函数调用 proxy(...args)
constructnew proxy(...args)

常用拦截示例

属性验证

JavaScript
const validator = {
  set(obj, prop, value) {
    if (prop === 'age' && typeof value !== 'number') {
      throw new TypeError('age must be a number');
    }
    if (prop === 'age' && value < 0) {
      throw new RangeError('age must be positive');
    }
    obj[prop] = value;
    return true;
  }
};

const person = new Proxy({}, validator);
person.age = 25;    // OK
person.age = -1;    // RangeError

私有属性

JavaScript
function createPrivate(obj) {
  return new Proxy(obj, {
    get(target, prop) {
      if (prop.startsWith('_')) {
        throw new Error('Cannot access private property');
      }
      return target[prop];
    },
    has(target, prop) {
      if (prop.startsWith('_')) {
        return false;
      }
      return prop in target;
    }
  });
}

函数拦截

JavaScript
function logCall(fn) {
  return new Proxy(fn, {
    apply(target, thisArg, args) {
      console.log(`调用函数,参数: ${args}`);
      return target.apply(thisArg, args);
    }
  });
}

const sum = logCall((a, b) => a + b);
sum(1, 2);  // 调用函数,参数: 1,2

Reflect API

Reflect 提供与 Proxy 拦截器对应的方法:

JavaScript
const obj = { name: 'Alice' };

// 读取
Reflect.get(obj, 'name');           // 'Alice'

// 设置
Reflect.set(obj, 'age', 25);        // true

// 检查存在
Reflect.has(obj, 'name');           // true

// 删除
Reflect.deleteProperty(obj, 'age'); // true

// 获取键列表
Reflect.ownKeys(obj);               // ['name']

Proxy + Reflect 配合

JavaScript
const proxy = new Proxy({}, {
  get(target, prop, receiver) {
    console.log(`get: ${prop}`);
    return Reflect.get(target, prop, receiver);
  },
  set(target, prop, value, receiver) {
    console.log(`set: ${prop} = ${value}`);
    return Reflect.set(target, prop, value, receiver);
  }
});

使用 Reflect 可确保操作正确传播,支持原型链继承场景

可撤销代理

JavaScript
const { proxy, revoke } = Proxy.revocable({ name: 'Alice' }, {
  get(target, prop) {
    return target[prop];
  }
});

proxy.name;  // 'Alice'
revoke();    // 撤销代理
proxy.name;  // TypeError: Cannot perform 'get' on a revoked proxy

要点总结

  • Proxy 拦截对象操作,实现访问控制、日志、验证等
  • Reflect 提供与 Proxy 对应的默认行为方法
  • 13 种拦截操作覆盖几乎所有对象操作
  • Proxy.revocable() 创建可撤销代理
  • Proxy + Reflect 是实现响应式框架的核心

📝 发现内容有误?点击此处直接编辑

← 上一篇 JavaScript 事件循环(Event Loop)
下一篇 → JavaScript 函数式编程
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库