当前位置:首页 > 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

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

js Proxy实现

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 的陷阱函数一一对应,通常用于在陷阱函数中调用默认行为。

js 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 还可以用于拦截函数的调用操作。

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实现动画

使用 CSS 动画与 JavaScript 控制 通过 JavaScript 动态添加或移除 CSS 类来触发动画。CSS 定义关键帧(@keyframes),JavaScript 通过 classL…

js实现倒计时

js实现倒计时

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

js实现图片放大缩小

js实现图片放大缩小

实现图片放大缩小的基础方法 使用CSS的transform: scale()属性可以快速实现图片的放大缩小效果。通过JavaScript动态修改该属性值: const img = document.…

js实现图表

js实现图表

在JavaScript中实现图表通常使用流行的图表库,以下是几种常见的方法和工具: 使用Chart.js Chart.js是一个简单灵活的库,适合快速生成响应式图表。安装方式包括CDN引入或npm安…

js实现预览

js实现预览

文件上传预览实现 使用JavaScript实现文件上传预览功能,可以通过FileReader对象读取文件内容并显示预览。以下代码支持图片、文本和PDF文件的预览: // HTML部分需要包含inpu…

js实现防洪

js实现防洪

防抖(Debounce)实现 防抖的核心思想是在事件触发后延迟执行回调函数,若在延迟时间内再次触发事件,则重新计时。适用于输入框搜索、窗口调整等场景。 function debounce(func,…