深浅拷贝

87 阅读3分钟

深浅拷贝

深浅拷贝只针对引用数据类型

浅拷贝--拷贝的是地址

如果是简单数据类型拷贝值,引用数据类型拷贝的是地址

例:浅拷贝,拷贝不了里面的famamily

  const obj = {
            name: 'ddd',
            famaliy: {
             
            }
        }

如果是单层对象,没问题,多层对象就有问题

拷贝对象

 <script>
        const obj = {
            name: 'justodit',
            age: 15
        }
        const Just = obj
        console.log(obj);
        Just.name='JUSTODIT'
        console.log(Just);
        console.log(obj);//obj里面得name也修改了
    </script>

解决办法

1、展开运算符

    const obj = {
            name: 'justodit',
            age: 18
        }
        //通过展开运算符放到新对象里面
        const OBJ = { ...obj }
        console.log(OBJ);
        OBJ.age=19
        console.log(OBJ);//age:19
        console.log(obj);//age:18 obj原来的值不会改变

2、Object.assign(空对象,要拷贝得对象)

        const obj = {
            name: 'justodit',
            age: 18
        }
        const OBJ={}
        Object.assign(OBJ,obj)
        console.log(OBJ);
        OBJ.age=19
        console.log(OBJ);//age:19
        console.log(obj);//age:18 obj原来的值不会改变

拷贝数组

1、空数组名.concat(要拷贝的数组名)

     const arr = [1, 2, 3];
        let arr1 = [];
        arr1 = arr1.concat(arr);
        arr1[0] = 3
        console.log(arr1); // 输出: [3, 2, 3]  
        console.log(arr);  // 输出: [1, 2, 3],arr 没有被改变

2、[...arr]

     const arr = [1, 2, 3];
        let arr1 = [...arr];
        arr1[0] = 3
        console.log(arr1); // 输出: [3, 2, 3]  
        console.log(arr);  // 输出: [1, 2, 3],arr 没有被改变

直接赋值和浅拷贝的区别

1、直接赋值的话,会互相影响,因为直接把对象或者数组里的地址也复制过去了

2、浅拷贝如果是一层对象就不受影响,多次对象就会互相影响

深拷贝

通过递归函数实现深拷贝

函数递归:如果一个函数在内部可以调用其本身,那么这个函数就是递归函数

1、函数内部自己调用自己

2、递归函数的作用和循环效果类似

3、递归很容易发生“栈溢出”错误(stacK overflow) ,所以必须要加退出条件return

    <script>
        let i = 1
        function fn() {
            console.log(`这是第${i}次调用`);
            if (i >= 6) {
                return

            }
            i++
            fn()
        }
        fn()
    </script>

递归函数使用例子:

<script>
        function getTime() {
        document.querySelector('div').innerHTML=new Date().toLocaleString()
        setTimeout(getTime,1000)
        }
        getTime()
    </script>

深拷贝拷贝出来的对象互不影响

1、要想实现深拷贝用到函数递归

2、当我们在普通拷贝时候,直接赋值就可以

3、如果遇到数组时,我再次调用递归函数

4、如果再次遇到对象,再次调用一次递归

5、先数组后对象 因为数组语属于对象

递归函数进行深拷贝

    <script>
        const obj = {
            uname: 'just',
            age: 15,
            hobby: ['篮球', ''],
            family: {
               name:'JUSTODIT'
            }
        }
        const o = {}
        function deepCopy(newObj, oldObj) {
            for (let key in oldObj) {
                //判断属性值是否是数组
                //'just'是否属于数组
                //15是否属于数组
                if (oldObj[key] instanceof Array) {
                    newObj[key] = []
                    // 再次递归
                    deepCopy(newObj[key], oldObj[key])
                } else if (oldObj[key] instanceof Object) {
                    newObj[key] = {}

                    deepCopy(newObj[key], oldObj[key])
                }
                else {
                    //k 属性名 uname age  oldObj[k]  属性值 18
                    // key是属性名 obj[key]属性值
                    //newObj===o.uname  给对象添加属性
                    newObj[key] = oldObj[key]
                }

            }
        }
        deepCopy(o, obj)
        o.age = 12
        o.hobby[0] = 'JUST'
        o.family.name='anything is possible'
        console.log(o);
        console.log(obj);
    </script>

代码深解释

 //第二遍循环---在数组内部的循环
        function deepCopy([], ['篮球', '']) {
            //key=索引号,oldObj[key] '篮球', ''
            for (let key in oldObj) {
                //判断属性值是否是数组
                //'just'是否属于数组
                //15是否属于数组
                if (oldObj[key] instanceof Array) {
                    //newObj[key] 接收 [] hobby
                    newObj[key] = []

                    deepCopy(newObj[key], oldObj[key])
                } else {
                    //k 属性名 uname age  oldObj[k]  属性值 18
                    // key是属性名 obj[key]属性值
                    //newObj===o.uname  给对象添加属性
                    newObj[0] = '篮球'
                    newObj[1] = ''
                }

            }
        }

js库lodash里面cloneDeep函数

    <!-- 先引用 -->
    <script src="./lodash.min.js"></script>
    <script>
         const obj = {
            uname: 'just',
            age: 15,
            hobby: ['篮球', ''],
            family: {
               name:'JUSTODIT'
            }
        }
        const deep=_.cloneDeep(obj)
        console.log(deep);
        deep.family.name='anything is possible'
        console.log(deep);
        console.log(obj);
    </script>

结果:

lodash.png

利用json实现深拷贝

步骤:

1、将对象变为JSON字符串 JSON.stringify(obj)

2、再把JOSN字符串转换为对象

    <script>
        const obj = {
            uname: 'just',
            age: 15,
            hobby: ['篮球', ''],
            family: {
                name: 'JUSTODIT'
            }
        }
        //将对象变为JSON字符串 JSON.stringify(obj)
        //再把JOSN字符串转换为对象
        const deep=JSON.parse(JSON.stringify(obj))
        deep.hobby[0]='bsae'
        deep.family.name='anything is possible'
        console.log(deep);
        console.log(obj);
    </script>