闭包构建动态规则校验引擎的核心是将规则封装为可复用、带上下文感知的纯函数,通过固化词法环境避免重复编译与作用域污染,支持参数绑定、缓存、条件组合与按需加载。

用闭包构建动态规则解析的校验引擎,核心在于把规则逻辑封装成可复用、带上下文感知能力的纯函数,同时避免重复编译与作用域污染。它不是写一堆 if-else,而是让每条规则成为“自包含、可组合、可缓存”的执行单元。
闭包如何承载动态规则
闭包天然保存其创建时的词法环境,这正好用来固化规则依赖的运行时参数——比如当前表单值、用户角色、时间戳或外部 API 响应缓存。例如:
- 一个“VIP价格上限”规则,可在初始化时捕获
currentUser.tier,后续校验直接读取,无需每次从全局查 - “确认密码一致”规则通过闭包绑定
passwordFieldRef,实现跨字段引用而不硬编码字段名 - 正则 pattern 规则可提前编译 RegExp 实例并封闭在闭包内,避免每次校验都 new RegExp 的开销
规则工厂:统一生成带状态的校验函数
不手动写每个闭包,而是设计一个规则工厂函数,输入配置,输出校验函数:
-
createRangeValidator({ min: 0, max: (ctx) => ctx.user.isVip ? 99999 : 999 })—— max 支持函数,运行时求值 - 工厂内部对函数类配置做 memoize,相同 ctx 结构下结果缓存,避免重复计算
- 返回的函数签名统一为
(value, context) => { valid: boolean, message?: string },便于管道串联
组合与管道:用闭包链实现规则流
多个规则不是堆在一起,而是用高阶闭包构造执行链:
-
and(rule1, rule2, rule3)返回新闭包,内部按序执行,任一失败即终止并返回错误 -
when((ctx) => ctx.form.mode === 'edit', required(), maxLength(200))—— 条件闭包只在满足时激活子规则 - 所有组合器本身也是闭包,能记住自己的配置和子规则引用,不产生中间对象
性能关键点:避免陷阱
闭包虽好,但滥用会拖慢性能:
- 不要在每次 render 或 input change 时新建闭包,规则实例应在 schema 解析阶段一次性生成并复用
- 异步规则(如用户名唯一性)用闭包封装 Promise 工厂,但需内置防抖/节流控制,避免高频触发请求
- 对大型表单,按字段分组构建闭包模块,支持按需加载和垃圾回收,而非全量驻留内存










