前端/移动开发面试题更新 2026-08-05

在JavaScript中,如何检测一个对象是否包含循环引用?请提供一个具体的代码实现。

前端/移动开发编码实现技术原理JavaScript

考察说明

考察对JavaScript对象引用机制的理解以及编写递归检测代码的能力。

回答思路

  1. 【回答框架 1】核心思路是利用WeakSet存储已访问的对象,通过递归遍历属性值,若遇到已访问对象则判定存在循环引用。
  2. 【回答框架 2】代码实现:定义函数isCircular(obj),创建WeakSet visited;递归内部函数check(current),若visited有current返回true,否则添加并遍历Object.keys(current),对每个属性值若为对象则递归调用check。
  3. 【回答框架 3】边界处理:需考虑非对象输入(如null、基本类型)直接返回false;也要注意函数、数组等引用类型,但WeakSet可统一处理。
  4. 【回答框架 4】复杂度:时间O(n),n为对象属性总数;空间O(n),用于存储visited,相比使用数组标记更高效,避免属性名冲突。
  5. 【回答框架 5】最终返回布尔值,示例代码可简化为使用try-catch结合JSON.stringify,但此方法有局限(如函数、undefined、循环引用会抛错),不如WeakSet方案可靠。
  6. 【关键点 1】使用WeakSet避免内存泄漏,且不修改原对象。
  7. 【关键点 2】递归遍历时先检查当前对象是否已访问。
  8. 【关键点 3】对非对象或null直接返回false。
  9. 【关键点 4】JSON.stringify检测循环引用会抛出TypeError,但无法处理非可序列化值。
  10. 【关键点 5】遍历时需使用Object.keys或for...in,但需排除Symbol属性(通常不需要)。
  11. 【易错点 1】不要使用全局数组记录已访问对象,否则容易误判同值非循环对象。
  12. 【易错点 2】使用JSON.stringify方法只能检测循环引用并抛错,无法返回精确位置,且无法处理函数。
  13. 【易错点 3】递归深度过大可能导致栈溢出,但通常对象深度有限。