React中console.log打印传入组件的对象出现无限递归引用问题问询
console.log 处理循环引用的底层逻辑
你遇到的是标准的循环引用(Circular Reference) 场景,本质是对象的某个属性引用指向了对象本身/上层对象,而非真的生成了无限层级的实体对象,浏览器console可以正常处理这类结构的核心逻辑如下:
- 首先JS中所有对象类型的值存储的都是内存地址引用,你示例中的
dynamicState全程是同一个内存地址的对象:你在组件A中给dynamicState.component赋值为引用了dynamicState本身的B组件,最终形成的结构是dynamicState.component.props.dynamicState === dynamicState,只是引用指向闭环,不存在无限层级的真实对象实体,不会额外占用无限内存。 - 浏览器的
console.log并不会在调用时就递归序列化整个对象的所有属性:- 调用
console.log时,浏览器仅会先记录对象的根引用,同时在控制台输出第一层属性的快照预览 - 当你点击展开属性时,控制台才会实时去读取当前引用指向的对象的属性值
- 遍历属性时浏览器内置了循环引用检测逻辑:如果读取到的属性引用已经在当前遍历路径中出现过,就会停止递归展开,而是标记为循环引用(Chrome等浏览器会直接展示
[Circular]标识),不会出现栈溢出问题。
你看到的无限嵌套的预览效果,本质是控制台渲染层做的可折叠交互,底层并没有真的存储无限层数据。
- 调用
示例代码
const SampleComponent = () => { const dynamicState = { component: <></> }; return <A dynamicState={dynamicState} />; }; interface AProps { dynamicState: { component: JSX.Element; }; } const A = (props: AProps) => { const { dynamicState } = props; dynamicState.component = <B dynamicState={dynamicState} />; console.log(dynamicState); return <></>; }; const B = (props: AProps) => { return <></>; };
控制台输出示例
{component: {…}} component: $$typeof: Symbol(react.element) key: null props: dynamicState: component: $$typeof: Symbol(react.element) key: null props: dynamicState: ....
内容的提问来源于stack exchange,提问作者Elvin
相关产品推荐
相关产品推荐

