深拷贝原生Javascript

原生Javascript深拷贝

深拷贝函数

实现代码可以直接复制,解析在下方

    /**
     * @parma {Object|Array} obj
     * @return {Object|Array} 
     * 返回一个新的引用类型实现深拷贝
     **/
        function deepCopy(obj) {
        if (typeof obj !== 'object') return obj
            var target = Array.isArray(obj) ? [] : {}
            for (var key in obj) {
                target[key] = obj[key]
                if (typeof obj[key] == 'object') {
                    target[key] = deepCopy(obj[key])
                }
            }
            return target
        }

浅拷贝和深拷贝

浅拷贝

  • 简单数据类型的赋值是在栈内开辟内存,直接存值

  • 复杂数据类型(引用类型)的赋值是在栈内留下地址,在堆内储存数据

  • 只在栈内实现

    • 复杂类型直接把一个变量赋给另一个变量时,只会把变量存的地址赋给另一个变量

    • 则浅拷贝是指复杂数据类型在赋值时,只把地址赋值给变量,两个变量都指向同一个堆里的数据,变量a的值改变,变量b的值也发生改变。这样具体实际应用意义不大,变量a,b都是同一个对象,那么用一个变量不就好了

深拷贝

  • 把对象(数组或复杂类型)a内的属性和值 一一遍历赋给变量b,如果对象a,其中某一属性的值是复杂类型则继续遍历此属性中的对象并赋值
var obj = {
    uname : '小明',
    age : 18,
    father : {
    	uname : '爸爸',
    	age : 48,
    	wife:{
    		uname:'妈妈'...
		}
	}
}

var newObj = {}
newObj.uname = '小明'
newObj.age = 18
newObj.father = {}
newObj.father.uname = '爸爸'
newObj.father.age = 48
newObj.father.wife = {}
newObj.father.wife.uanem = '妈妈'
...

暴力拷贝

function deepCloen(obj) {
    // 当前循环的对象
    var cur = {}
    // obj为被循环的对象
    for (var key in obj) {
        if (typeof obj[key] === 'object') {
            cur[key] = deepCloen(obj[key])
        } else {
            cur[key] = obj[key]
        }
    }
    //  开始向上返回结果
    return cur
}

思路:创建空对象,判断当前循环是不是复杂类型,是的话则调用方法本身再次循环判断,如果是简单类型直接赋值,如果for in 循环结束遍历,说明本次所有结果都是简单类型,开始向上返回结果

方法缺点:如果是数组的话,也会被改为对象,简单但是不好用

实现深拷贝

 /**
 * @parma {Object|Array} obj
 * @return {Object|Array} 
 * 返回一个新的引用类型实现深拷贝
 **/
function deepCopy(obj) {
	// 简单类型直接返回
	if (typeof obj !== 'object') return obj
    // 判断是数组还是对象
    var flag = Array.isArray(obj)
    // 当前循环的引用类型
    var cur = flag ? [] : {}

    for (var key in obj) {
        // if结构优化,先赋值,如果这次是对象,重新赋值
        cur[key] = obj[key]
        if (typeof obj[key] == 'object') {
            cur[key] = deepCopy(obj[key])
        }
    }
    // 循环到最后时开始向上返回值,把每次的结果
    return cur
}

思路:在暴力拷贝的基础上多了判断,flag作为判断标致,控制创建对象还是数组,并且for in循环也能拷贝数组

测试

var obj = {
    uname: '孙悟空',
    team: {
        master: '唐僧',
        shenxian: undefined,
        bros: [{ uname: '八戒', hobbit: 'eat' }, '沙僧', '小白龙']
    }
}

function deepCopy(obj) {
    var flag = Array.isArray(obj)
    var target = flag ? [] : {}
    for (var key in obj) {
        target[key] = obj[key]
        if (typeof obj[key] == 'object') {
            target[key] = deepCopy(obj[key])
        }
    }
    return target
}

// 测试
var myObj = deepCloen(swk)
console.log(myObj)
obj.team.bros[1] = '悟净'
obj.team.bros[0].hobbit = 'sleep'
console.log(obj);

  • 如果改变原对象obj的值,新对象myObj不会改变,说明深度拷贝实现
    请添加图片描述

借助工具轻松实现

1.JSON newObj=JSON.parse(JSON.stringify(obj))
 // 不能识别undefined
2.jQuery  $.extend(true,newObj,obj)
 // 不能识别undefined
3.lodash  newObj=_.cloneDeep(obj)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值