Js Proxy使用代理拦截动态属性,灵活控制对象访问的实战技巧

更新日期: 2025-06-09阅读: 162标签: 代理

前端开发中,你是否遇到过这些痛点:

  • 需要为动态生成的属性添加统一逻辑

  • 希望在属性访问时自动执行校验或转换

  • 需要创建高度灵活的数据结构但不想写大量胶水代码

Proxy对象正是解决这些问题的利器,能拦截并自定义对象的底层操作。今天我们就深入探讨如何利用Proxy拦截动态属性,提升代码的灵活性和可维护性。


一、Proxy基础:创建你的第一个拦截器

Proxy是ES6引入的元编程特性,基本语法

const proxy = new Proxy(target, handler)

实现基础属性拦截:

const user = { name: "小明" };

const userProxy = new Proxy(user, {
  get(target, property) {
    console.log(`正在访问属性: ${property}`);
    return target[property];
  },
  set(target, property, value) {
    console.log(`设置 ${property} = ${value}`);
    target[property] = value;
    return true; // 表示设置成功
  }
});

userProxy.age = 25; // 控制台输出: 设置 age = 25
console.log(userProxy.name); // 输出: 正在访问属性: name → "小明"


二、动态属性实战:5个实用拦截场景

1. 自动类型转换器

const numberConverter = new Proxy({}, {
  set(target, prop, value) {
    // 尝试转换为数字
    const numValue = Number(value);
    target[prop] = isNaN(numValue) ? value : numValue;
    return true;
  }
});

numberConverter.price = "99.9"; // 自动转为数字
console.log(typeof numberConverter.price); // "number"

2. 敏感字段过滤器

const sensitiveFilter = new Proxy({}, {
  set(target, prop, value) {
    const sensitiveFields = ["token", "password"];
    
    if (sensitiveFields.includes(prop)) {
      // 对敏感字段进行脱敏处理
      target[prop] = "*".repeat(value.length);
    } else {
      target[prop] = value;
    }
    return true;
  }
});

sensitiveFilter.password = "secret123";
console.log(sensitiveFilter.password); // "*********"

3. 动态默认值生成器

const withDefaults = new Proxy({}, {
  get(target, prop) {
    // 动态生成不存在的属性
    if (!(prop in target)) {
      target[prop] = `默认值_${Date.now()}`;
    }
    return target[prop];
  }
});

console.log(withDefaults.newField); // "默认值_1620000000000"

4. 属性访问记录器(调试神器)

function createTracker(obj) {
  const accessedProps = new Set();
  
  return new Proxy(obj, {
    get(target, prop) {
      accessedProps.add(prop);
      return target[prop];
    },
    getAccessedProps() {
      return Array.from(accessedProps);
    }
  });
}

const obj = { a: 1, b: 2 };
const trackedObj = createTracker(obj);

trackedObj.a;
trackedObj.b;
console.log(trackedObj.getAccessedProps()); // ["a", "b"]

5. 动态表单验证器

const formValidator = new Proxy({}, {
  set(target, prop, value) {
    const rules = {
      email: v => /@/.test(v),
      age: v => v >= 18
    };
    
    if (rules[prop] && !rules[prop](value)) {
      throw new Error(`${prop} 验证失败`);
    }
    
    target[prop] = value;
    return true;
  }
});

formValidator.email = "valid@example.com"; // 成功
formValidator.age = 16; // 抛出错误: age 验证失败


三、Proxy的高级应用技巧

1. 链式拦截组合

const withLogging = obj => new Proxy(obj, {
  get(target, prop) {
    console.log(`Get ${prop}`);
    return target[prop];
  }
});

const withValidation = obj => new Proxy(obj, {
  set(target, prop, value) {
    if (value === undefined) {
      throw new Error(`不能设置undefined值`);
    }
    target[prop] = value;
    return true;
  }
});

// 组合多个代理
const user = withValidation(withLogging({}));
user.name = "测试"; // 控制台输出: Get name

2. 性能敏感场景优化

// 按需创建的Proxy优化性能
const createLazyProxy = () => {
  let realTarget = {};
  let proxy = null;

  return {
    set(prop, value) {
      if (!proxy) realTarget[prop] = value;
      else proxy[prop] = value;
    },
    getProxy() {
      if (!proxy) {
        proxy = new Proxy(realTarget, {
          // 添加复杂拦截逻辑
        });
      }
      return proxy;
    }
  };
};


四、实战注意事项

  1. 浏览器兼容性:Proxy在IE中不兼容(可使用polyfill如proxy-polyfill)

  2. 性能考量:频繁操作的代码路径避免复杂拦截逻辑

  3. 不可代理的特殊对象:Date、Map等内置对象可能需要特殊处理

  4. 避免过度使用:明确使用场景,简单需求用普通对象更高效


五、真实应用场景

  1. api响应适配器:动态转换后端返回的数据结构

  2. 状态管理中间件:在Redux/vuex中跟踪状态变更

  3. 表单管理库:自动处理字段验证和转换

  4. 数据观察系统:实现类似Vue的响应式系统

  5. 权限控制层:动态限制对象属性的访问权限


总结

Proxy提供的动态属性拦截能力,让我们能够以声明式的方式控制对象行为。相比传统的Object.defineProperty,它具有更强大的拦截范围和更简洁的语法。通过本文的实用案例,你可以立即在项目中应用这些技术

  • 为动态属性添加统一逻辑

  • 实现灵活的数据验证

  • 创建智能默认值系统

  • 构建高性能的调试工具

提示:Proxy不是万能的银弹,但在处理动态属性、元编程和抽象边界问题时,它能大幅减少样板代码,提升开发效率。掌握这一特性,将为你的前端工具箱增添一件强大武器。

链接: https://fly63.com/article/detial/12735

什么是在线代理ip网页代理

当我们需要大量IP进行快节奏完成业绩的时候,很多人都会想到去IP代理服务商那里购买IP代理,所以我相信很多人对于IP代理这个词已经有一定的认识了,那么还有一个词叫做:在线代理ip网页代理

centos7下搭建高匿HTTP代理

一般适用情况:1、两台都有外网IP,一台服务器请求资源通过另外一个服务器,本文重点讲第一种。2、两台服务器,其中一台服务器只有内网IP,另外一台服务器有公网和内网IP。

.Net Core/Framework之Nginx反向代理后获取客户端IP等数据探索

公司项目最近出现获取访问域名、端口、IP错误现象,通过排查发现, 之前项目一直通过Nginx自定义Headers信息来获取,但最近运维人员失误操作造成自定义Header信息丢失,造成项目拿不到对应的数据。

反向代理和内网穿透

反向代理看上去看深奥,其实不然,只是因为汉语言文化的差异导致它看上去深奥。一般反派感觉都比较厉害和神秘。要理解反向代理,我们就不得不说一下正向代理。正向代理代理的对象是客户端;反向代理代理的对象是服务端

反向代理Cloudflare加速网站(SNIproxy)

写在教程前:为什么要反向代理cloudflare?答:缩短路由,加快cloudflare节点到大陆用户的速度,用过cloudflare的用户应该知道,这家CDN的速度在除了大陆以外的地方访问都非常快,那么又没有什么办法使其对大陆访问良好呢?

ES6中的代理(Proxy)和反射(Reflection)

调用 new Proxy() 可常见代替其它目标 (target) 对象的代理,它虚拟化了目标,所以二者看起来功能一致。代理可拦截JS引擎内部目标的底层对象操作,这些底层操作被拦截后会触发响应特定操作的陷阱函数。

Vue多环境代理配置

多人协作模式下,修改代理比较麻烦,而且很容易某个开发人员会修改了vue.config.js文件后提交了。第一,很容易引起冲突。 第二,很容易出现代理错误,需要排查。而且现在微服务盛行

node.js代理访问

本地开发,代理访问,防止跨域(一般通过webpack配置代理即可),特殊情况如携带一些自定义的登录cookie则需要通过自己写node,作为一种server中间层,单线程异步可以缓解服务器压力

vue proxy代理跨域

changeOrigin的属性值为一个布尔值,如果设置为true,那么本地会虚拟一个NODE服务端接收你的请求并代你发送该请求(中间件)。[本质上是本地开了一个服务器dev-server,所有的请求都通过这里转发出去。]

Nginx反向代理之动静分离

我们已经知道了什么是正向代理与反向代理,这次我们就讲一下Nginx的动静分离的案例,其实质运用的就是反向代理,专门用一台服务器代理服务器上的图片资源。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!