数组/ 对象的深浅克隆

浅克隆

  1. 把对象进行克隆
    //1. Object.assign()
    let obj = {
    	a:1,
    	b:2,
    	c:3		
    };
    let new_obj = Object.assign({},obj);
    new_obj === obj // false
    // 2. 还可以通过循环实现对象的克隆
    let new_obj = {};
    _.each(obj, (value, key) => { //_.each调用的是自己封装的utils.js中的each方法
         new_obj[key] = value;
    });
    // ...
    
  2. 把数组进行克隆
    let ary = [1,2,3,4,5];
    // let new_ary = ary.slice();
    // let new_ary = ary.slice(0);
    // let new_ary = ary.splice(0);
    // let new_ary = ary.concat([]);
    // let new_ary = ary.concat();
    // let new_ary = [...ary];	
    // ...
    //new_ary === ary // => false
    

以上的方案都是浅克隆:
在这里插入图片描述

深度克隆

方法一:JSON.parse(JSON.stringify([value])):

  • JSON.stringify([value]) : 把对象/数组变为JSON字符串
  • JSON.parse([value]) : 把JSON字符串变为对象/数组【浏览器需要重新开辟所有内存】
  • 弊端:
    • 不允许出现套娃现象,例如:window. window = window
    • 属性值不能是BigInt
    • 丢失一些内容:属性值为symbol/ undefined/ function …
    • 部分信息不准确:
      • 正则 -> 空对象
      • Error -> 空对象
      • 日期对象 -> 转换时刻的时间字符串
  • 属性值要避开以上类型数据

方法二:Qs.parse(Qs.stringify([val]))

  • Qs.stringify([value]) : 把对象/数组变为urlencoded格式字符串 : “ xxx=xxx&xxx=xxx ”
  • Qs.parse([value]) : 把urlencoded格式字符串变为对象/数组【浏览器需要重新开辟所有内存】
  • 弊端:
    • 不允许出现套娃现象,例如:window. window = window
    • 丢失一些内容:属性值为 正则表达式/ undefined/ Error …
    • 部分信息不准确:
      • 布尔值 -> 字符串
      • 数字 -> 字符串
      • symbol -> 字符串
      • BigInt -> 字符串
      • null -> “”
      • 日期 -> 转换时刻的时间字符串
  • 属性值要避开以上类型数据

数组/对象的深浅拷贝(克隆)

// 实现数组和对象深/浅拷贝
var clone = function clone() {
    var target = arguments[0],//目标元素,被拷贝的值
        deep = false,//是否深拷贝
        type,//传入的数据类型
        isArray,//是否是数组
        isObject,//是否是对象
        result,//拷贝后的结果,最后返回拷贝后的结果
        Ctor,//当前数据所属的类
        treated = arguments[arguments.length - 1];//标记是否处理过
    //treated不是数组,或者treated.treated部位true,就是没处理过,添加处理标记,否则什么也不做
    !Array.isArray(treated) || !treated.treated ? (treated = [], treated.treated = true) : null;
    
    //如果第一个参数是布尔值,则需要要处理深拷贝问题,target取第二个参数
    if (typeof target === "boolean") { 
        deep = target;
        target = arguments[1];
    };
    // 防止死递归的处理
    if (treated.indexOf(target) > -1) return target;
    treated.push(target);
    
    // 校验类型
    type = toType(target);
    isArray = Array.isArray(target);//是否是数组
    isObject = isPlainObject(target);//是否是纯对象,isPlainObject来自utils.js

    // 特殊值的拷贝
    //只是null或者undefined 直接返回
    if (target == null) return target; 
    Ctor = target.constructor;//获取当前数据所属的类
   	//正则或者数据直接new操作
    if (/^(regexp|date)$/i.test(type)) return new Ctor(target);
    //错误类型new操作传入的是error.message
    if (/^(error)$/i.test(type)) return new Ctor(target.message); 
    //函数返回一个匿名函数,直接执行传入函数,并把参数传递给匿名函数,函数的直接结果和传入的函数执行结果一致
    if (/^(function|generatorfunction)$/i.test(type)) {
        return function proxy() {
            var args = Array.from(arguments);
            return target.apply(this, args);
        };
    };
    // 其余既不是数组又不是对象的直接返回
    if (!isArray && !isObject) return target;

    // 如果是数组/对象,我们依次迭代赋值给新的数组/对象
    result = new Ctor();
    //遍历target, each为utils内封装的遍历数组/对象的方法
    each(target, function (copy, name) {
        if (deep) {
            // 深拷贝:基于递归再次处理
            result[name] = clone(deep, copy, treated);
            return;
        }
        // 浅拷贝
        result[name] = copy;
    });
    return result;
};

utils.js:封装了一些常用的方法

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值