分享更有价值
被信任是一种快乐

Javascript深度克隆中的循环引用问题怎么解决

文章页正文上

这篇文章主要介绍“Javascript深度克隆中的循环引用问题怎么解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Javascript深度克隆中的循环引用问题怎么解决”文章能帮助大家解决问题。
概要
在前端项目开发中,我们经常需要深度克隆JS对象。在克隆代码开发过程中,我们经常会遇到数组判定或对象循环引用的问题。
本文通过实例来解决上述问题
代码及实现
常见深度克隆JS对象的代码
function deepClone(origin){
if (origin == undefined || typeof origin !== “object”){
return origin;
}
if (origin instanceof Date){
return new Date(origin);
}
let keys = Reflect.ownKeys(origin);
let target = {};
if (Object.prototype.toString.call(origin) === “[object Array]”){
target = [];
}
for(let key of keys){
target[key] = deepClone(origin[key]);
}
return target;
}
上述代码主要存在两个问题:
数组判定代码过于麻烦
对象中如果出现循环引用,代码将会报错。
循环引用代码:
var obj = {a: 1};
obj.obj1 = obj;
var newObj = deepClone(obj);
console.log(newObj);
错误信息:
产生错误的原因很简单,由于对象中存在循环引用,所以递归无法结束,最后内存溢出了。
循环引用问题的解决
由于对象中的循环引用,所以递归无法结束。如果我们记录下哪个对象被克隆了,哪个对象没有被克隆,就可以强制结束递归,避免内存泄漏。
我们选择WeekMap来记录对象是否被克隆,主要考虑以下三点:
WeakMap对象是key => value形式,不会重复记录
WeakMap对象的key必须是一个对象
WeakMap是若引用,如果不再使用,内存空间直接释放。
改进代码如下:
function deepClone(origin, map = new WeakMap()){
if (origin == undefined || typeof origin !== “object”){
return origin;
}
if (origin instanceof Date){
return new Date(origin);
}
if (origin instanceof RegExp){
return new RegExp(origin);
}
var copied = map.get(origin);
if (!!copied){
return copied;
}
let target = {};
if (Object.prototype.toString.call(origin) === “[object Array]”){
target = [];
}
map.set(origin, target);
let keys = Reflect.ownKeys(origin);
for(let key of keys){
target[key] = deepClone(origin[key], map);
}
return target;
}
通过WeakMap记录对象是否被拷贝过,如果拷贝过,就直接将拷贝过的对象返回,不再重复克隆
如果没有被拷贝过,构建数组或普通JS对象,然后再进行记录。
克隆存在循环引用的对象,代码如下:
var obj = {a: 1};
obj.obj1 = obj;
var newObj = deepClone(obj);
console.log(newObj);
执行结果如下:
数组判定的代码优化
在克隆之前,我们必须知道要克隆的对象是一个普通JS对象还是一个数组。我们是否可以换一个思路,任何对象都有自己的构建器,如果我们直接使用构造器构造对象,也就不需要之前对象是什么类型了。
JS中所有对象都有自己的原型链,原型链中包含基类Object的构造器,如下所示:
JS普通对象
JS数组:
JS普通对象的构造方法可以构建出{},JS数组的构建方法可以构造出[]。所以如果我们调用该构造方法,就无需再去判定数组还是普通对象了。
改进后的代码如下:
function deepClone(origin, map = new WeakMap()){
if (origin == undefined || typeof origin !== “object”){
return origin;
}
if (origin instanceof Date){
return new Date(origin);
}
var copied = map.get(origin);
if (!!copied){
return copied;
}
let target = new origin.constructor();
map.set(origin, target);
let keys = Reflect.ownKeys(origin);
for(let key of keys){
target[key] = deepClone(origin[ke免费云主机、域名y], map);
}
return target;
}关于“Javascript深度克隆中的循环引用问题怎么解决”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注云技术行业资讯频道,小编每天都会为大家更新不同的知识点。

相关推荐: Canvas入门实战之怎么实现一个图形验证码

这篇文章主要介绍“Canvas入门实战之怎么实现一个图形验证码”,在日常操作中,相信很多人在Canvas入门实战之怎么实现一个图形验证码问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Canvas入门实战之怎么实现一个图形验证码”…

文章页内容下
赞(0) 打赏
版权声明:本站采用知识共享、学习交流,不允许用于商业用途;文章由发布者自行承担一切责任,与本站无关。
文章页正文下
文章页评论上

云服务器、web空间可免费试用

宝塔面板主机、支持php,mysql等,SSL部署;安全高速企业专供99.999%稳定,另有高防主机、不限制内容等类型,具体可咨询QQ:360163164,Tel同微信:18905205712

主机选购导航云服务器试用

登录

找回密码

注册