深拷贝和浅拷贝的区别,怎么解决浅拷贝问题,栈和堆与数据类型拷贝的关系

深拷贝(deepCopy):增加了一个指针并申请了一个新的内存,新的指针指向新的内存地址。

浅拷贝(shallowCopy):只增加了一个新指针指向已存在的内存地址。浅拷贝只复制一层对象的属性。

栈(stack)为自动分配的内存空间,它由系统自动释放;而堆(heap)则是动态分配的内存,大小不定也不会自动释放。

结合栈和堆与数据类型拷贝的关系去理解:

1.基本类型--名,值,都存储在栈内存中,例如:let a = 1; [name:a;value:1]

2.当你复制 b = a;会开辟一个新的栈空间,存放b的名和值,这也就是说,修改b并不会影响到a

3.引用数据类型--名存在栈内存中,值存在于堆内存中,栈内存会提供一个引用的地址指向堆内存中的值;即在栈内存中原本存放value的值,变成了存放引用地址;

4.所以当引用类型进行 b = a;实际上拷贝的是栈里面的引用地址,而不是真正的值(在堆里面);修改b的时候,会影响到a,这就是浅拷贝

所以深拷贝实现,就是在堆中为b新开辟存放值的空间。

怎么实现深拷贝?怎么解决浅拷贝?

1.将一个对象转为json对象。然后再解析这个json对象

let obj = {a:{b:22}};
let copy = JSON.parse(JSON.stringify(obj));

2.lodash的cloneDeep

3.Vue.extend(),jq的$.extend( [deep ], target, object1 [, objectN ] )

4.递归去复制所有层级属性【或是循环,其实所有方式的原理,都是复制层级的属性值】

 参考Zepto 中深拷贝的代码:   

// 内部方法:用户合并一个或多个对象到第一个对象
    // 参数:
    // target 目标对象  对象都合并到target里
    // source 合并对象
    // deep 是否执行深度合并
    function extend(target, source, deep) {
        for (key in source)
            if (deep && (isPlainObject(source[key]) || isArray(source[key]))) {
                // source[key] 是对象,而 target[key] 不是对象, 则 target[key] = {} 初始化一下,否则递归会出错的
                if (isPlainObject(source[key]) && !isPlainObject(target[key]))
                    target[key] = {}

                // source[key] 是数组,而 target[key] 不是数组,则 target[key] = [] 初始化一下,否则递归会出错的
                if (isArray(source[key]) && !isArray(target[key]))
                    target[key] = []
                // 执行递归
                extend(target[key], source[key], deep)
            }
            // 不满足以上条件,说明 source[key] 是一般的值类型,直接赋值给 target 就是了
            else if (source[key] !== undefined) target[key] = source[key]
    }

    // Copy all but undefined properties from one or more
    // objects to the `target` object.
    $.extend = function(target){
        var deep, args = slice.call(arguments, 1);

        //第一个参数为boolean值时,表示是否深度合并
        if (typeof target == 'boolean') {
            deep = target;
            //target取第二个参数
            target = args.shift()
        }
        // 遍历后面的参数,都合并到target上
        args.forEach(function(arg){ extend(target, arg, deep) })
        return target
    }

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值