当前位置:首页 > JavaScript

js Proxy实现

2026-02-01 00:45:29JavaScript

Proxy 的基本概念

Proxy 是 ES6 引入的一个功能,用于创建一个对象的代理,从而可以拦截和自定义对象的基本操作。通过 Proxy,可以拦截对象的属性访问、赋值、枚举等操作,并对其进行自定义处理。

创建 Proxy

Proxy 的构造函数接受两个参数:目标对象和处理程序对象。处理程序对象包含一系列拦截操作的钩子函数(也称为“陷阱”)。

const target = {};
const handler = {
  get: function(target, prop, receiver) {
    return Reflect.get(...arguments);
  }
};
const proxy = new Proxy(target, handler);

常用的拦截操作

Proxy 支持多种拦截操作,以下是一些常见的陷阱函数:

get

拦截对象属性的读取操作。

const handler = {
  get: function(target, prop) {
    return prop in target ? target[prop] : 37;
  }
};
const proxy = new Proxy({}, handler);
console.log(proxy.a); // 37

set

拦截对象属性的赋值操作。

const handler = {
  set: function(target, prop, value) {
    if (prop === 'age' && typeof value !== 'number') {
      throw new TypeError('Age must be a number');
    }
    target[prop] = value;
    return true;
  }
};
const proxy = new Proxy({}, handler);
proxy.age = 25; // 成功
proxy.age = '25'; // 抛出 TypeError

has

拦截 in 操作符。

const handler = {
  has: function(target, prop) {
    return prop.startsWith('_') ? false : prop in target;
  }
};
const proxy = new Proxy({ _secret: 'foo', public: 'bar' }, handler);
console.log('_secret' in proxy); // false
console.log('public' in proxy); // true

deleteProperty

拦截 delete 操作符。

const handler = {
  deleteProperty: function(target, prop) {
    if (prop.startsWith('_')) {
      throw new TypeError('Private properties cannot be deleted');
    }
    delete target[prop];
    return true;
  }
};
const proxy = new Proxy({ _secret: 'foo', public: 'bar' }, handler);
delete proxy.public; // 成功
delete proxy._secret; // 抛出 TypeError

Reflect 的使用

Reflect 对象提供了一系列静态方法,用于执行对象操作。这些方法与 Proxy 的陷阱函数一一对应,通常用于在陷阱函数中调用默认行为。

const handler = {
  get: function(target, prop, receiver) {
    console.log(`Getting property ${prop}`);
    return Reflect.get(target, prop, receiver);
  }
};
const proxy = new Proxy({ a: 1 }, handler);
console.log(proxy.a); // 输出 "Getting property a" 然后输出 1

Proxy 的常见应用场景

数据验证

通过 set 陷阱函数,可以在属性赋值时进行数据验证。

const validator = {
  set: function(target, prop, value) {
    if (prop === 'age' && (typeof value !== 'number' || value < 0)) {
      throw new TypeError('Age must be a positive number');
    }
    target[prop] = value;
    return true;
  }
};
const person = new Proxy({}, validator);
person.age = 25; // 成功
person.age = '25'; // 抛出 TypeError

私有属性

通过 hasget 陷阱函数,可以模拟私有属性。

const handler = {
  has: function(target, prop) {
    return prop.startsWith('_') ? false : prop in target;
  },
  get: function(target, prop, receiver) {
    if (prop.startsWith('_')) {
      throw new TypeError('Cannot access private property');
    }
    return Reflect.get(target, prop, receiver);
  }
};
const proxy = new Proxy({ _secret: 'foo', public: 'bar' }, handler);
console.log('_secret' in proxy); // false
console.log(proxy._secret); // 抛出 TypeError

函数调用拦截

Proxy 还可以用于拦截函数的调用操作。

js Proxy实现

const handler = {
  apply: function(target, thisArg, argumentsList) {
    console.log(`Called with arguments: ${argumentsList}`);
    return Reflect.apply(target, thisArg, argumentsList);
  }
};
const proxy = new Proxy(function(a, b) { return a + b; }, handler);
console.log(proxy(1, 2)); // 输出 "Called with arguments: 1,2" 然后输出 3

注意事项

  • Proxy 的陷阱函数必须返回正确的值,否则可能导致意外的行为。例如,set 陷阱函数必须返回一个布尔值。
  • Proxy 的性能比直接操作对象稍差,因此在性能敏感的场景中需要谨慎使用。
  • 某些操作无法被拦截,例如对象的 typeof 操作或 instanceof 操作。

标签: jsProxy
分享给朋友:

相关文章

js实现倒计时

js实现倒计时

使用 setInterval 实现倒计时 通过 setInterval 定时器每秒更新剩余时间,适用于简单倒计时场景。 function countdown(seconds, callback) {…

js 进度条的实现

js 进度条的实现

使用 HTML 和 CSS 创建基础进度条 HTML 结构可以简单使用一个 div 元素作为容器,内部嵌套另一个 div 表示进度: <div class="progress-containe…

js实现论坛

js实现论坛

实现论坛的基本功能 使用JavaScript实现一个论坛需要结合前端和后端技术。前端可以使用React、Vue或Angular等框架,后端可以选择Node.js配合Express或Koa框架。数据库可…

js实现dh

js实现dh

JavaScript 实现 DH(Diffie-Hellman)密钥交换 Diffie-Hellman(DH)密钥交换是一种安全协议,允许双方在不安全的通信信道上建立一个共享密钥。以下是如何在 Jav…

js实现vue路由

js实现vue路由

Vue 路由的基本实现 在 Vue.js 中实现路由功能通常使用 Vue Router 库。Vue Router 是 Vue.js 官方的路由管理器,用于构建单页面应用(SPA)。 安装 Vue R…

js实现吸色

js实现吸色

使用Canvas实现吸色功能 通过Canvas的getImageData方法获取像素颜色数据。创建一个Canvas元素,将目标图像绘制到Canvas上,通过鼠标事件获取坐标对应的颜色值。 c…