object.hasown 不受循环引用影响,仅检查对象自有属性,时间复杂度 o(1),安全高效;循环引用仅影响深拷贝、序列化等操作,检测需额外实现。

Object.hasOwn 不能处理循环引用对象的属性检查问题,它本身不涉及循环引用检测,也不会因循环引用而报错或失效——但它检查的是对象自身属性,和循环引用无关。
Object.hasOwn 的作用很明确
它只判断一个对象是否拥有某个**自有属性(own property)**,即该属性直接定义在对象上,而非继承自原型链。无论对象是否存在循环引用,只要属性存在且是自身的,就返回 true;否则返回 false。
- 循环引用只是对象之间相互持有引用(比如
a.b = b; b.a = a),不影响属性的存储结构 -
Object.hasOwn(obj, 'key')底层调用的是 [[HasProperty]] 内部方法,不遍历嵌套对象,不递归,也不访问属性值 - 即使某个属性值是循环引用的对象,只要这个属性名确实存在于目标对象上,
hasOwn就能正确返回true
循环引用真正影响的是深比较、序列化或遍历操作
比如 JSON.stringify(obj) 遇到循环引用会抛出错误,structuredClone() 在旧环境可能失败,深度克隆或遍历时若没做引用去重也会陷入死循环。但 Object.hasOwn 完全不触发这些行为。
- ✅ 安全:传入含循环引用的对象不会导致栈溢出或异常
- ✅ 快速:只查一层属性键,时间复杂度 O(1)
- ❌ 无关:它既不检测循环引用,也不受其影响
如果你真想检测循环引用,需要额外逻辑
要判断一个对象是否存在循环引用,需手动跟踪已访问对象,例如用 WeakMap 记录路径:
- 递归遍历所有可枚举/自有属性值
- 对每个引用类型值,检查是否已在访问路径中出现过
- 遇到重复引用即判定为循环引用
这和 Object.hasOwn 是完全独立的功能,不能混用。
实际使用建议
检查属性是否存在时,放心用 Object.hasOwn(obj, key),哪怕 obj 是个“环状结构”。但若后续要序列化、克隆或深度遍历它,才需要提前考虑循环引用防护。
- 替代
obj.hasOwnProperty(key)(更安全,不依赖对象原型) - 避免用
key in obj(会查原型链,可能误判) - 无需为循环引用专门加 try/catch 或预处理











