如何判断一个js对象是否存在循环引用

一、背景

在前端JSON.stringfy是我们常用的一个方法,可以将一个对象序列化。 例如将如下对象序列化

const person = { name: 'kalory', age:18}JSON.stringfy(person)
// 结果
'{"name":"kalory","age":18}'将一个数组序列化const arr = [1,2,3,4,5]
// 结果
'[1,2,3,4,5]'const persons = [{ name: 'kalory', age:18},{ name: 'jack', age:48}]
// 结果
'[{"name":"kalory","age":18},{"name":"jack","age":48}]'

我们发现上面对象是可以使用JSON.stringfy序列化的。

  • 但是如果一个对象存在循环引用,序列化会报错,如下 person对象的owner属性指向了自己,存在循环引用
const person = { name: 'kalory', age:18}
person.onwer = person

我们对上面这个对象进行JSON.stringfy,结果如下,会报错:

image.png

我们发现他说不能转化一个“圈结构体为JSON”,是因为这个对象的owner属性指向了自己。在转化的时候会变成死循环。

  • 那么我们如果判断一个对象有没有环呢?

二、实现

2.1 思路

我们判断一个对象有没有循环引用,我们其实并不需要在乎对象的key是什么,只需要判断对象的value。如果value是引用数据类型的时候,有没有指向对象的某一值。

所以我们可以先使用Object.values()拿到对象所有values,然后定义一个cache变量用来存储values中的引用数据类型,然后遍历values

如果cache中存在,那么说明这个对象有环 return true,如果不存在并且是引用数据类型,那么我们就加入cache。当values遍历完都没有reutrn那么说明没有环return false

2.2 递归实现

function existCircular(obj) {let cache = new Set(); function helper(obj) {let values = Object.values(obj);for (let i = 0; i < values.length; i++) {if (cache.has(values[i])) {return true;}// 不是引用数据类型,直接跳过if(typeof values[i] !== 'object' || values[i] === null) continuecache.add(values[i]);let flag = helper(values[i]);// 如果 flag 是 false, 那么继续遍历,如果是 true,说明已经存在环了, 直接 return trueif (flag) {return true;}}return false;}return helper(obj);
}// 测试
const person = { name: 'kalory', age:18}
person.onwer = personexistCircular(person) // true

2.3 BFS实现

const existCircularBFS = (obj) => {let cache = new Set();let values = [obj];while(values.length) {const item =  values.shift()if (cache.has(item)) {return true;}// 基本数据类型跳过if(typeof item !== 'object' || item === null) continuecache.add(item);// 主要这里 Object.values 拿到的是一个数组,我们需要展开push到values// 如果直接 push Object.values(item) 会造成死循话values.push(...Object.values(item))}return false;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/28373.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么是分布式光伏系统?

随着全球对可再生能源和环保技术的日益重视&#xff0c;分布式光伏系统已成为电力领域中不可或缺的一部分。它代表了一种新兴的能源供应方式&#xff0c;具有显著的环保和经济价值。 一、定义与特点 分布式光伏系统是指将光伏组件安装在用户侧&#xff0c;如屋顶、墙面等建筑物…

OperationalError: (_mysql_exceptions.OperationalError)

OperationalError: (_mysql_exceptions.OperationalError) (2006, MySQL server has gone away) 这个错误通常表示客户端(例如你的 Python 程序使用 SQLAlchemy 连接到 MySQL 数据库)和 MySQL 服务器之间的连接被异常关闭了。这个问题可能由多种原因引起,以下是一些常见的原…

ModuleNotFoundError: No module named ‘distutils‘的解决办法

最近想试试odoo17&#xff0c;在windows环境下&#xff0c;想安装试验一下&#xff0c;结果老出现oduleNotFoundError: No module named ‘distutils‘错误。查了一下&#xff0c;以为是python版本导致的&#xff0c;结果试了很多版本如下&#xff1a; 试了几个&#xff0c;每个…

Java——变量作用域和生命周期

一、作用域 1、作用域简介 在Java中&#xff0c;作用域&#xff08;Scope&#xff09;指的是变量、方法和类在代码中的可见性和生命周期。理解作用域有助于编写更清晰、更高效的代码。 2、作用域 块作用域&#xff08;Block Scope&#xff09;&#xff1a; 块作用域是指在…

windows设备/路由设备上ip地址如何查看、使用

在Windows设备上查看本地IP地址&#xff08;IPv4和IPv6&#xff09;&#xff1a; 使用命令提示符&#xff1a; 打开命令提示符&#xff08;在Windows中按Win R&#xff0c;然后输入"cmd"并按Enter&#xff09;。在命令提示符窗口中&#xff0c;输入以下命令以查看…

Redis缓存穿透、缓存雪崩和缓存击穿的解决方案

Redis缓存穿透、缓存雪崩和缓存击穿的解决方案 引言 Redis作为当前非常流行的内存数据结构存储系统&#xff0c;以其高性能和灵活性被广泛应用于缓存、消息队列、排行榜等多种场景。然而&#xff0c;在实际使用过程中&#xff0c;可能会遇到缓存穿透、缓存雪崩和缓存击穿等问…

软件服务中的 SLA 到底是什么?

目录 什么是 SLA SLA 的组成部分 SLA 的重要性 制定和执行 SLA 小结 平常使用云服务或者使用 SaaS 服务时&#xff0c;厂商一般都会承诺 SLA 达到多少&#xff0c;没有达到的话会如何赔偿&#xff0c;例如云服务的稳定性一般会承诺4个9&#xff08;即99.99%&#xff09;。…

C语言:进程

一、进程标识符pid 类型pid_t&#xff0c;16位整型数三万多个。2的16次方65535. 进程标识是顺次向下使用。与文件描述符不一样。 pid_t getpid(void); pid_t getppid(void); 进程正常终止 1.从main函数返回 2.调用exit 3.调用_exit或_Exit 4.最后一个线程…

软考中级|软件设计师-知识点整理

目录 计算机网络概论 计算机系统基础知识 中央处理单元 数据表示 校验码 计算机体系结构 计算机体系结构的发展 存储系统 输入/输出技术 安全性、可靠性与系统性能评测基础知识 加密技术和认证技术 计算机可靠性 程序设计语言基础知识 程序设计语言概述 程序设计…

微信同声传译小程序插件使用教程

微信同声传译小程序插件 —— 机器翻译、智能语音 案例可搜索“一起学英语鸭”小程序查看&#xff0c; 实现效果如下图&#xff1a; 插件功能 语音转文字 语音合成 文本翻译 step 1&#xff1a;添加插件 在使用前&#xff0c;需要登录官网 设置 → 第三方服务 → 添加插件…

Hadoop的读写流程

Hadoop分布式文件系统(HDFS)是Apache Hadoop项目的核心组件,它为大数据存储提供了一个可靠、可扩展的存储解决方案。本文将详细介绍HDFS的读写数据流程,包括数据的存储原理、读写过程以及优化策略。 一、HDFS简介 HDFS是一个高度容错的分布式文件系统,它设计用于运行在通…

AI探索:最佳落地应用场景

如果说今年的风口&#xff0c;那一定是 AI。不过AI像一把双刃剑&#xff0c;既有助益也有风险。我们将从IBM Watson的高飞与坠落&#xff0c;到Google Allo的黯然失色&#xff0c;探索AI应用中的教训。同时&#xff0c;瑞幸咖啡的成功故事展现了凭借策略得当的AI应用&#xff0…

2024年【安全员-C证】考试资料及安全员-C证找解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 安全员-C证考试资料根据新安全员-C证考试大纲要求&#xff0c;安全生产模拟考试一点通将安全员-C证模拟考试试题进行汇编&#xff0c;组成一套安全员-C证全真模拟考试试题&#xff0c;学员可通过安全员-C证找解析全真…

自学前端第一天

HTML标签 ’HTML‘全程是‘hypertext Markup langage(超文本标记语言) HTML通过一系列的’标签&#xff08;也称为元素&#xff09;‘来定义文本、图像、链接。HTML标签是由尖括号包围的关键字。 标签通常成对存在&#xff0c;包括开始标签和结束标签&#xff08;也称为双标签…

探索AI创新的前沿——从零开始学习和运用SpringAI

1.SpringAI介绍 SpringAI是AI工程师的一个应用框架&#xff0c;它提供了一个友好的API和开发AI应用的抽象&#xff0c;旨在简化AI应用的开发工序。 目标是将可移植性和模块化设计等设计原则应用于AI领域的Spring生态系统&#xff0c;并将POJO作为应用程序的构建块推广到AI领域…

浅谈赚钱的四个级别,你在哪一层呢

一谈到赚钱&#xff0c;很多人都会扯到&#xff1a;智商、情商、人脉、资源、背景等等&#xff0c;类似“小钱靠勤&#xff0c;中钱靠智&#xff0c;大钱靠德”这样的经典语录都会脱口而出&#xff0c;其实从本质上来讲&#xff0c;都没有错&#xff0c;但这样的说法太缥缈&…

mysql-connector下载教程(手把手)

下载一个第三方库主要有三种途径&#xff1a; 去官方网站 Oracle 官网去github去Maven中央仓库 前两个方法比较麻烦&#xff0c;你还需要去找。 这里就只介绍maven的方法 Maven类似于手机app的应用商店。 操作步骤&#xff1a; 点击右边进入官网Maven中央仓库 在搜索框中…

k8s+pv+pvc+nas 数据持久化volumes使用

1 k8s pod申请持久化卷配置 apiVersion: v1 kind: Service metadata:name: $IMG_NAMEnamespace: rz-dtlabels:app: $IMG_NAME spec:type: NodePortports:- port: 8091nodePort: 31082 #service对外开放端口selector:app: $IMG_NAME --- apiVersion: apps/v1 kind: Deployment …

FineReport简单介绍(2)

一、报表类型 模板设计是 FineReport 学习过程中的主要难题所在&#xff0c;FineReport 模板设计主要包括普通报表、聚合报表、决策报表三种设计类型。 报表类型简介- FineReport帮助文档 - 全面的报表使用教程和学习资料 二、聚合报表 2-1 介绍 聚合报表指一个报表中包含多个…

C# —— do_while循环

基本语法 while 循环 先判断条件是否满足 再进行循环 do...while 循环 是先执行一遍 循环体里面的逻辑 再判断是否继续执行 do{// do while 循环语句块Console.WriteLine("这是一个do...while循环");} while (bool值)(循环判断条件);*//*do{Console.WriteLine(&qu…