zoukankan      html  css  js  c++  java
  • 深浅拷贝 详解

    对象的深浅拷贝

    1.浅拷贝的方法

    • =

      • 直接赋值改变其中的一个数组另一个数组也会变

         let arr1=[1,2,3,4]
                 let arr2=arr1;
                 arr1[0]=9;
                 console.log(arr1);//[9, 2, 3, 4]
                 console.log(arr2);// [9, 2, 3, 4]
    • assign

      • 利用对象的自带方法 Object.assign({},obj)

         let obj = {
                     people:{
                        age:20
                     }
                }
                let p = Object.assign({},obj)
                p.people.age=30;
                console.log(p.people.age);//30
                console.log(obj.people.age);//30

         

    • {...arr}

      • es6中的数组解构赋值来拷贝

         

        let arr = [
                        {
                           age:20
                        },{
                            name:'李四'
                        }
                    ]
                let arr1={...arr};
                arr1[1].name="张三"
                console.log(arr[1].name);// 张三
                console.log(arr1[1].name);// 张三

         

    • concat

      • 利用数组自带的方法 Array.prototype.concat()

        let arr = [
                        {
                           age:20
                        },{
                            name:'李四'
                        }
                    ]
                let arr1={...arr};
                arr1[1].name="张三"
                console.log(arr[1].name);// 张三
                console.log(arr1[1].name);// 张三

         

    • slice

      • 数组的截取方法

        let arr = [
                    1,3,
                        {
                           age:20
                        }
                    ]
                let arr1 = arr.slice() 
                arr1[2].age=30;
                console.log(arr[2].age); //30   
                console.log(arr1[2].age); //30 

         

    注意:关于Array的slice和concat方法的补充说明:Array的slice和concat方法不修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组。

    原数组的元素会按照下述规则拷贝:

    如果该元素是个对象引用(不是实际的对象),slice 会拷贝这个对象引用到新的数组里。两个对象引用都引用了同一个对象。如果被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变。 对于字符串、数字及布尔值来说(不是 String、Number 或者 Boolean 对象),slice 会拷贝这些值到新的数组里。在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组。

    例如:

      
    let arr = [
                1,3,
                    {
                       age:20
                    }
                ]
            let arr1 = arr.slice() 
            arr1[0]=2;
            console.log(arr[0]);//1
            console.log(arr1[0]);//2

     

    2.深拷贝方法

    • JSON.parse(JSON.stringify())

      • 原理: 用JSON.stringify将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝。

        这种方法虽然可以实现数组或对象深拷贝,但不能处理函数

              
         let arr = [
                        {
                           age:20
                        },{
                            name:'李四'
                        }
                    ]
                let arr1=JSON.parse(JSON.stringify(arr));
                arr1[1].name="张三"
                console.log(arr[1].name);// 李四
                console.log(arr1[1].name);// 张三

           

         

    • 手写递归方法

      • 递归方法实现深度克隆原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝

        let arr = [
                    {name:'li'}, 
                    {age:12},
                    ()=>{return 4}
                 ]
                let arr1 = deepClone(arr)//调用函数克隆
                console.log(arr1[2]);//()=>{return 4} 可以克隆函数
                console.log(arr === arr1);//false 因为深克隆引用地址不同
                arr1[0].name = "张三"
                console.log(arr[0].name);// li
                console.log(arr1[0].name);// 张三
        // 获取对象的类型
                function getObjType(target) {
                    return Object.prototype.toString.call(target).slice(8, -1)
                }
                // 执行深克隆
                function deepClone(data) {
                    var type = getObjType(data);
                    var obj;
                    if (type === 'Array') {
                        obj = [];
                    } else if (type === 'Object') {
                        obj = {};
                    } else {
                        //不再具有下一层次
                        return data;
                    }
                    if (type === 'Array') {
                        for (var i = 0, len = data.length; i < len; i++) {
                            obj.push(deepClone(data[i]));
                        }
                    } else if (type === 'Object') {
                        for (var key in data) {
                            obj[key] = deepClone(data[key]);
                        }
                    }
                    return obj;
                };

         

     

    不停学习,热爱是源源不断的动力。
  • 相关阅读:
    线程的中断.interrupt
    线程的加入.join()
    Runnable接口
    线程Thread类
    求和、均值
    最值、对应索引位置
    数组、冒泡排序
    获取Methods成员方法类
    获取Field成员变量类
    基于WinDbg的内存泄漏分析
  • 原文地址:https://www.cnblogs.com/ximenchuifa/p/13909375.html
Copyright © 2011-2022 走看看