可借助object.create(null)基座、原型链继承与proxy拦截构建轻量数据清洗链:基座挂纯函数,实例隔离状态,proxy实现链式调用与动态委托。

直接用原型链本身无法实现“拦截”,但可以借助其级联查找特性 + Object.create(null) 基座 + Proxy 封装,构建出真正轻量、无框架依赖、可复用的数据清洗链。核心不是“在原型上挂过滤器”,而是让每个清洗步骤作为只读能力注入原型,所有实例共享逻辑但隔离状态。
用 Object.create(null) 创建纯净清洗基座
避免污染和隐式继承干扰是清洗链可靠的前提。真实对象(如普通 {})自带 toString、hasOwnProperty 等方法,可能被误调或触发副作用;而 Object.create(null) 创建的对象完全无原型,干净可控:
- 定义清洗基座:
const cleanBase = Object.create(null); - 只挂安全、幂等、无副作用的清洗函数,例如:
cleanBase.trim = (s) => typeof s === 'string' ? s.trim() : s;cleanBase.toNumber = (s) => Number(s) || 0;cleanBase.removeEmpty = (arr) => arr.filter(Boolean); - 这些函数不操作外部状态,输入确定、输出确定,符合清洗组件的纯函数要求
子清洗器通过原型链继承并隔离写入
每个具体清洗任务创建独立实例,自动继承基座能力,但所有数据中间态、配置、临时缓存都落在自身,不影响他人:
安装并运行 Aperture(Lightning Labs 的 L402 闪电反向代理),用于创建 L402 付费墙、配置付费 API 端点、为其他代理托管付费内容或测试 L402 认证流程。
const userCleaner = Object.create(cleanBase);- 可扩展专属逻辑:
userCleaner.normalizeName = (n) => n?.replace(/\s+/g, ' ').toUpperCase(); - 执行时调用继承方法:
userCleaner.trim(' john ') → 'john',查不到就沿原型链找到cleanBase.trim - 修改自身属性(如
userCleaner.skipFields = ['id'])不会影响cleanBase或其他清洗器
用 Proxy 实现链式调用与动态拦截
仅靠原型链只能“读取”能力,无法控制执行顺序、跳过步骤、记录日志或短路异常。此时用 Proxy 封装清洗器实例,接管 get 行为,实现链式语义:
- 拦截
get:当访问cleaner.filterName时,不直接返回函数,而是返回一个包装后的“可链式调用函数” - 该函数内部自动绑定当前清洗上下文,并支持
.then(nextFilter)或.skipIf(...)等轻量 API - 示例:
cleaner.trim().toNumber().clamp(0, 100)—— 每次调用返回新代理对象,保持前序结果并透传给下一步 -
set拦截禁止覆盖基座方法,确保清洗逻辑不可篡改;has拦截隐藏非清洗相关属性,避免误用
组合清洗步骤时按需委托,不预加载
不需要把所有清洗函数提前塞进对象。利用原型链的动态查找 + Proxy 的懒执行,可实现“用到才查、查到才跑”:
- 定义一个通用委托清洗器:
const delegateCleaner = new Proxy(Object.create(null), { get(t, p) { if (p in builtInFilters) return builtInFilters[p]; if (p in customSteps) return customSteps[p]; return () => undefined; } }); - 清洗链可写作:
delegateCleaner.stripHtml().removeEmoji().sanitizeXss(),只有调用某步时才去原型或注册表里找对应函数 - 支持运行时热插拔:
builtInFilters.sanitizeXss = myNewXssFn;,后续所有使用该清洗器的实例立即生效










