js如何判断原型链是否有循环引用

来源:Python编程网作者:广州网站建设头衔:草根站长
导读:本期聚焦于小伙伴创作的《js如何判断原型链是否有循环引用》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《js如何判断原型链是否有循环引用》有用,将其分享出去将是对创作者最好的鼓励。

在JavaScript中,每个对象都有对应的原型对象,对象通过__proto__属性或者Object.getPrototypeOf方法向上查找原型,形成原型链。正常情况下原型链的终点是null,但如果某个对象的原型指向了链中已经出现过的对象,就会产生循环引用,导致属性查找时无限循环。

js如何判断原型链是否有循环引用

原型链循环引用的常见场景

循环引用通常出现在手动修改原型指向的场景中,比如下面这种错误写法:

// 错误示例:构造循环原型链
function A() {}
function B() {}
A.prototype = new B();
B.prototype = new A(); // 此时A和B的原型互相指向,形成循环

const a = new A();
// 访问a的属性时,会沿着A实例 -> B实例 -> A.prototype -> B.prototype -> A.prototype...无限循环

判断原型链是否有循环引用的核心思路

判断的核心逻辑是遍历对象的原型链,同时记录已经访问过的原型对象,如果遍历过程中遇到了已经记录过的对象,就说明存在循环引用。具体步骤如下:

  • 初始化一个集合,用来存储遍历过程中遇到的所有原型对象
  • 从当前对象的原型开始,依次向上获取原型对象
  • 每次获取原型后,检查该原型是否已经在集合中,如果在则说明有循环,如果不在就加入集合
  • 如果原型为null,说明遍历到了原型链终点,没有循环

具体实现方法

方法一:使用Set存储原型对象

Set可以自动去重,适合用来记录已经访问过的原型,实现代码如下:

function hasPrototypeCycle(obj) {
  // 处理非对象或者null的情况
  if (obj === null || typeof obj !== 'object') {
    return false;
  }
  const visitedPrototypes = new Set();
  let currentProto = Object.getPrototypeOf(obj);
  while (currentProto !== null) {
    // 如果当前原型已经在集合中,说明存在循环
    if (visitedPrototypes.has(currentProto)) {
      return true;
    }
    // 把当前原型加入集合
    visitedPrototypes.add(currentProto);
    // 继续向上获取原型
    currentProto = Object.getPrototypeOf(currentProto);
  }
  // 遍历到null,没有循环
  return false;
}

方法二:使用数组存储并比较引用

如果不想使用Set,也可以用数组存储原型,通过includes方法判断是否出现过,代码如下:

function hasPrototypeCycle(obj) {
  if (obj === null || typeof obj !== 'object') {
    return false;
  }
  const protoList = [];
  let currentProto = Object.getPrototypeOf(obj);
  while (currentProto !== null) {
    if (protoList.includes(currentProto)) {
      return true;
    }
    protoList.push(currentProto);
    currentProto = Object.getPrototypeOf(currentProto);
  }
  return false;
}

方法验证

我们用之前的循环原型链示例来验证方法是否有效:

function A() {}
function B() {}
A.prototype = new B();
B.prototype = new A();

const a = new A();
console.log(hasPrototypeCycle(a)); // 输出true,存在循环引用

// 正常对象的原型链检测
const normalObj = {};
console.log(hasPrototypeCycle(normalObj)); // 输出false,无循环

注意事项

需要注意几个边界情况:

  • 传入的参数如果不是对象或者是null,直接返回false,因为基础类型没有原型链
  • Object.getPrototypeOf是标准方法,比直接使用__proto__兼容性更好,推荐优先使用
  • 如果原型链非常长,遍历过程的时间复杂度是O(n),n是原型链长度,属于可接受范围
原型链循环引用在常规开发中很少见,但如果涉及到动态修改原型、实现自定义继承逻辑时,建议提前用上述方法做检测,避免出现难以排查的运行时错误。

JavaScript原型链循环引用原型判断修改时间:2026-07-14 23:03:20

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。