如何检测JavaScript选项对象中的意外属性,无需重复维护属性列表
解决方案
你可以通过解构剩余参数+默认配置对象的方案实现需求,全程只需要声明一次允许的属性,修改时也只需维护一处,完全不需要手动同步属性列表。
最简实现(无额外封装)
利用对象解构的剩余运算符,你可以直接捕获所有不在预期内的属性,判断是否存在未知属性即可:
function log(text, opts = {}) { // 解构时用...unknownOpts接收所有未明确声明的属性 const { times = 1, silent = false, logger = console, ...unknownOpts } = opts; // 仅开发/调试阶段执行校验,生产环境自动跳过不影响性能 if (process.env.NODE_ENV !== 'production') { const unknownKeys = Object.keys(unknownOpts); if (unknownKeys.length > 0) { throw new Error(`log函数收到未知选项:${unknownKeys.join('、')}`); } } // 原有业务逻辑不变 if (silent) return; for (let i = 0; i < times; i++) { logger.log(text); } }
测试效果和你预期完全一致:
- 调用
log( "Hello World!", {times:1} )正常执行 - 调用
log( "Bye World!", {times:2, slient:true} )会直接抛出错误:log函数收到未知选项:slient
可维护性更强的封装方案
如果你的选项较多、或者需要在多个地方复用校验逻辑,可以把允许的属性和默认值统一抽成独立的配置对象,完全避免属性不同步的问题:
// 仅维护这一处配置即可,增删属性都在这里改 const LOG_DEFAULT_OPTS = { times: 1, silent: false, logger: console } // 通用校验工具(可全局复用) function validateOpts(opts, defaultOpts, funcName = '') { // 生产环境直接跳过校验 if (process.env.NODE_ENV === 'production') return; const allowedKeys = Object.keys(defaultOpts); const unknownKeys = Object.keys(opts).filter(key => allowedKeys.includes(key) === false); if (unknownKeys.length) { throw new Error(`${funcName}收到未知选项:${unknownKeys.join('、')},允许的选项为:${allowedKeys.join('、')}`); } } function log(text, opts = {}) { // 校验调用只需要传配置对象即可,不用手动写属性列表 validateOpts(opts, LOG_DEFAULT_OPTS, 'log'); // 合并默认值 const { times, silent, logger } = { ...LOG_DEFAULT_OPTS, ...opts }; // 原有业务逻辑不变 if (silent) return; for (let i = 0; i < times; i++) { logger.log(text); } }
如果后续需要新增/删除选项,只需要修改LOG_DEFAULT_OPTS一个地方即可,校验逻辑、默认值会自动同步,不会出现遗漏更新的问题。如果是必填不需要默认值的属性,直接在配置对象里赋值为undefined即可。
TypeScript 场景额外优化
如果你使用TypeScript,可以直接在类型层面完成校验,传多余属性时编译阶段就会报错,不需要额外写运行时代码:
type LogOpts = { times?: number silent?: boolean logger?: Console } function log(text: string, opts: LogOpts = {}) { // 原有逻辑 }
内容的提问来源于stack exchange,提问作者Blue Nebula
相关产品推荐
相关产品推荐

