You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测表单验证函数是否访问了表单模型参数

如何检测表单验证函数是否访问了表单模型参数

这个需求特别实际——要是验证器根本没用到表单模型的数据,那模型变化时确实没必要重复跑验证,能省下不少不必要的性能开销。我给你推荐一个精准又可行的方案,基于Proxy来追踪模型是否被访问,而且它的开销远没有你担心的那么大~

具体实现思路

核心逻辑就是用Proxy包装你的表单模型,当任何验证器访问模型的属性时,我们就标记“模型已被访问”。这种方式能精准识别实际用到模型数据的验证器,哪怕验证器声明了第二个参数但完全没使用它,也不会误判。

修改后的完整代码如下:

const formModel = {
  firstname: 'Bill',
  lastname: 'Gates',
  departureDate: new Date(),
  returnDate: new Date()
};

const value = 'Test';

const nonAccessValidators = [
  v => v ? null : 'required',
  v => v?.length ?? 0 > 1 ? null : 'incomplete' 
];

const accessValidators = [
  v => v ? null : 'required',
  (v, m) => v > m.departureDate ? null : 'before-date'
];

const runValidators = (value, formModel, validators) => {
  let formModelAccessed = false;

  // 创建Proxy追踪模型的属性访问
  const trackedModel = new Proxy(formModel, {
    get(target, prop) {
      // 只要访问了模型的任意属性,就标记为已访问
      formModelAccessed = true;
      return target[prop];
    },
    // 兜底处理设置属性的情况(验证器一般只读,但留个保险)
    set() {
      formModelAccessed = true;
      return true;
    }
  });

  const errors = validators.reduce((acc, validator) => {
    const error = validator(value, trackedModel);
    if (error) {
      acc.push(error);
    }
    return acc;
  }, []);

  return { formModelAccessed, errors };
};

const nonAccessErrors = runValidators(value, formModel, nonAccessValidators);
const accessErrors = runValidators(value, formModel, accessValidators);

// 测试结果:
// nonAccessErrors -> { formModelAccessed: false, errors: [] }
// accessErrors -> { formModelAccessed: true, errors: ['before-date'] }

方案细节说明

  1. 精准追踪访问行为:只有当验证器真正读取(或写入)模型的属性时,才会触发Proxy的拦截逻辑,把formModelAccessed设为true。像那种只接收第二个参数但完全不用它的验证器,不会触发标记,完全符合你的需求。
  2. 性能开销可忽略:Proxy是浏览器原生支持的高效特性,创建和运行的成本极低,哪怕每次模型变化都创建新的Proxy,在实际业务场景中也几乎不会有性能感知。
  3. 兼容性友好:Proxy在所有现代浏览器和Node.js环境都能正常运行,除非你需要兼容IE这类超老环境,否则完全不用顾虑兼容性问题。

不推荐的替代方案

比如通过validator.toString()解析函数体来判断是否引用第二个参数,这种方法很容易失效:

  • 代码压缩后参数名会被混淆(比如变成(a,b)=>...),无法准确识别;
  • 函数如果是通过bind、高阶函数等方式创建的,toString的结果可能不符合预期;
  • 无法区分“声明了参数但未使用”和“实际使用参数”的情况。

所以Proxy的方案是目前最靠谱的选择。

备注:内容来源于stack exchange,提问作者Adrian Brand

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 19:42:59