一、JSON.parse(JSON.stringify(obj))实现深拷贝
前端使用到对象的深度复制通常会简单的使用JSON.parse(JSON.stringify(obj))实现 (浅表复制会用Array.from、Object.assign、Object.create静态方法实现),但在对象存在循环引用的情况下(比如:树结构中子对象存在parent属性存放父对象引用的情况)只是使用JSON.stringify(obj)会导致 “TypeError: Converting circular structure to JSON” 的循环引用错误:
这种情况可以利用JSON.stringify的可选参数“replacer”来解决问题
JSON.stringify 语法
JSON.stringify(value[, replacer [, space]])相关知识点: toJSON 方法
以下解决方法是传递函数作为“replacer”参数,过滤掉“_parent”属性(还有一种更简单的方式是传递“不包含_parent属性名,只包含所需要属性的名字的字符串数组”作为“replacer”参数即可轻松解决上面的错误):
以上代码中,this.MilestoneTrees是一个树状结构的数组,其中子结节中的“_parent”属性存放着对父节点的引用,这种情况直接只用“JSON.stringify(this.MilestoneTrees)”会导致文中开头所示的错误
![]()
还有一种解决方法,见以下文章,原理也是一样的,全文如下:
https://blog.51cto.com/u_15311558/5758502
在使用JSON.stringify方法去转化成字符串,会报错TypeError: Converting circular structure to JSON
原因: 对象中有对自身的循环引用;
解决方法:
下面的 json_str 就是JSON.stringify 转换后的字符串
var cache = []; var json_str = JSON.stringify(json_data, function(key, value) { if (typeof value === 'object' && value !== null) { if (cache.indexOf(value) !== -1) { return; } cache.push(value); } return value; }); cache = null; //释放cache //来源: https://blog.51cto.com/u_15311558/5758502
二、structuredClone 深拷贝简介
注意: 用 JSON.parse(JSON.stringify(obj)) 实现深拷贝是一种奇技淫巧,在包含一般数字、字符串等类型属性的对象确实是种不错的方法,但存在一些短板,详细可见以下文章,另一种常见的方案是利用工具库Lodash 的 cloneDeep
函数
而现在的前端原生提供了全局的 structuredClone
函数用于深拷贝, 该方法利用可选的transfer参数还支持把原始值中的可转移对象转移到新对象,而不是把属性引用拷贝过去。 可转移对象与原始对象分离并附加到新对象;它们不可以在原始对象中访问被访问到。
structuredClone() - Web API 接口参考 | MDN
structuredClone(value)
structuredClone(value, { transfer }) //transfer 可选,是一个可转移对象的数组,里面的 值 并没有被克隆,而是被转移到被拷贝对象上。