先讲一个常见的误区:想判断动态计算的属性名是否存在于对象中,很多人习惯写 obj[computedKey] !== undefined。这种做法存在不小隐患——万一属性的值恰好是 undefined,它就会错误地认为属性不存在。更稳健的做法是直接使用 in、hasOwnProperty 或 Reflect.has,把计算结果当作字符串传入即可,无需硬编码属性名。

用 in 运算符检测(含原型链)
这是最直接的方法,无论属性是对象自身的还是继承而来的,只要存在于该对象上就算找到。语法简洁:computedKey in obj,其中 computedKey 是字符串类型的计算结果。例如:const key = 'user' + id; if (key in data) { ... }。
需要注意:key 必须为字符串。如果传入数字,in 会自动转为字符串;但如果传入的是 symbol 类型变量,in 会直接报错,不会自动转换。
用 hasOwnProperty 检测(仅自身属性)
如果你只关心对象“自身定义”的属性,而不希望包含原型链上的,那就用 hasOwnProperty。写法为 obj.hasOwnProperty(computedKey)。
但也需警惕:如果对象重写了 hasOwnProperty 方法,直接调用可能引发问题。所以业界推荐加一层安全调用:Object.prototype.hasOwnProperty.call(obj, computedKey)。例如:const field = `${type}Count`; if (Object.prototype.hasOwnProperty.call(config, field)) { ... }。虽然多写几个字符,但安全系数大大提升。
用 Reflect.has(现代、语义清晰)
ES6 引入的 Reflect.has,行为与 in 完全一致,但写法更函数式,且对参数有严格校验。语法:Reflect.has(obj, computedKey)。其优势在于:如果 obj 是 null 或 undefined,它会直接抛出错误,而非静默失败——这对调试非常友好。
同样,Reflect.has 对 symbol 类型的 key 支持有限,除非你显式传入 Symbol 变量。但对于字符串计算结果,它完全胜任。
避开常见陷阱
再次强调:不要用 obj[computedKey] !== undefined 判断属性是否存在。例如:const user = { name: undefined }; const k = 'name'; user[k] !== undefined // 结果为 false,但 name 属性明明存在——这种场景就是典型的误判。
正确做法始终是使用 in、hasOwnProperty 或 Reflect.has。另外,为确保 computedKey 为字符串类型,可在计算时加一层 String(key) 或直接用模板字面量兜底,能有效避免隐式转换带来的意外。
