js深拷贝和浅拷贝

js对象分为基本类型复合(引用)类型,基本类型存放在栈内存,复合(引用)类型存放在堆内存。

js的深浅拷贝只针对复杂数据类型(object,array)的复制问题,深浅拷贝都能实现在已有对象上复制一份的作用,但是对象的实例是存储在堆内存中然后通过一个引用值去操作对象,因此拷贝分两种情况,拷贝引用和拷贝实例,这是深浅拷贝的区别。

浅拷贝:拷贝引用,拷贝后的引用都是指向同一个对象的实例,彼此之间的操作会相互影响。

深拷贝:在堆中重新分配内存,并且把原对象的所有属性都进行新建拷贝,拷贝后的对象与原来的对象完全隔离,互不影响。


一。数组的深浅拷贝

<script type="text/javascript">
    /*数组的浅拷贝*/
    var arr = [1,3,3];
    var arrcopy = arr;//arr赋值给arrcopy
    arrcopy[1]="copy";
    console.log(arr);//[1, "copy", 3]
    console.log(arrcopy);//[1, "copy", 3]
</script>
这种是浅拷贝,但是我们想要的是arr的值不会随arrcopy的值的改变而改变对么?这里用到数组的深拷贝解决,常用方法有Array.prototype.slice()     Array,prototype.concat()     jQuery的$.extend({},obj),以及ES6的两种新的复制方法,不会发生引用,分别是Array.from(要复制的数组)     ...(这个方法也可以用在函数的形参上面)。

1.方法一,数组的深拷贝(Array.prototype.slice()

<script type="text/javascript">
    /*数组的深拷贝*/
    var arr = [1,2,3];
    var arrcopy = arr.slice(0);
    arrcopy[1] = 'copy';
    console.log(arr);//[1, 2, 3]
    console.log(arrcopy);//[1, "copy", 3]
</script>
2.方法二,数组的深拷贝( Array,prototype.concat()

<script type="text/javascript">
    /*数组的深拷贝---Array,prototype.concat()*/
    /*concat() 方法用于连接两个或多个数组,该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。*/
    var arr = [1,2,3,4];
    var arrcopy = arr.concat();
    arrcopy[1] = 'copy';
    console.log(arr);//[1, 2, 3, 4]
    console.log(arrcopy);//[1, "copy", 3, 4]
</script>

二。ES6中深拷贝

1.第一种:Array.from(要复制的数组)

<script type="text/javascript">
    /*数组深拷贝ES6的两种方法*/
    /*第一种:Array.from(要复制的数组)*/
    var arr = [1,2,3];
    var arrcopy = Array.from(arr);
    arr.push(4);
    console.log(arr);//[1, 2, 3, 4]
    console.log(arrcopy);//[1, 2, 3]
    arrcopy.push('copy');
    console.log(arr);//[1, 2, 3, 4]
    console.log(arrcopy);//[1, 2, 3, "copy"]
</script>

2.第二种:...

<script type="text/javascript">
    /*数组深拷贝ES6的两种方法*/
    /*第二种:...*/
    var arr = [1,2,3,4,5];
    var arrcopy = [...arr];
    arr.push(6);
    console.log(arr);//[1, 2, 3, 4, 5, 6]
    console.log(arrcopy);//[1, 2, 3, 4, 5]
    arrcopy.push('copy');
    console.log(arr);//[1, 2, 3, 4, 5, 6]
    console.log(arrcopy);//[1, 2, 3, 4, 5, "copy"]
</script>

第二种方法...用到函数的形参上

<script type="text/javascript">
    /*数组深拷贝ES6的两种方法*/

    /*...这个方法也可以用在函数的行参上面。*/
    var arr = [1,2,3,5];
    function show(...arr) {//直接来复制arguments这个伪数组,让它变成真正的数组,从而拥有数组的方法。
        console.log(arr);//[1,2,3,5]
        arr.push(6);
        console.log(arr);//[1,2,3,5,6]
    }
    show(arr);
</script>

三。对象的深浅拷贝

1.对象的浅拷贝

<script type="text/javascript">
    //最简单的对象浅拷贝
    var a = {c:1};
    var b = a;
    console.log(a === b);//true
    console.log(b.c)//1
</script>
2.对象的深拷贝,常见的方法有:JSON.parse()    JSON.stringify()   jQuery的$.extend(true,{},obj)  等。

<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript">
    /*对象的深拷贝*/
    var a = {b:{c:1}};
    var d = $.extend(true,{},a);
    console.log(a===d);//false
    a.b.c = 3;
    console.log(d.b.c);//输出1,没有改变
</script>
通过循环来复制JSON.stringify()[从一个对象中解析出字符串]

<script type="text/javascript">
    /*深拷贝---通过循环来复制*/
    var arr = [1,2,3];
    var newarr = [];
    for(var i=0;i<arr.length;i++){
        newarr[i]=arr[i];
    }
    arr.push(5);
    newarr.push('new');
    console.log(arr);//[1, 2, 3, 5]
    console.log(newarr);//[1, 2, 3, "new"]
    //json
    var json1 = {"name":"pxq","age":25,"job":"前端开发"};
    var json2 = {};
    for(var name in json1){
        json2[name] = json1[name];
    }
    console.log(JSON.stringify(json1));//{"name":"pxq","age":25,"job":"前端开发"}
    console.log(JSON.stringify(json2));//{"name":"pxq","age":25,"job":"前端开发"}
    json1.a = 1;
    json2.b = 2;
    console.log(JSON.stringify(json1));//{"name":"pxq","age":25,"job":"前端开发","a":1}
    console.log(JSON.stringify(json2));//{"name":"pxq","age":25,"job":"前端开发","b":2}
</script>
深复制,复制一个复杂的对象,可以用 递归 的思想来写,节省性能,不会发生引用。

<script type="text/javascript">
    /*而深复制的话,我们要求复制一个复杂的对象,那么我们就可以利用递归的思想来做,及省性能,又不会发生引用。*/
//    var json1 = {"arr1":[1,2,3,4],"name":"pxq","age":25};
    var json1 = {"arr1":[1,2,3,4]};
    var json2 = {};
    function copy(obj1,obj2){ //obj1=[1,2,3,4],obj2=[]
        var obj2 = obj2 || {}; //最初的时候给它一个初始值等于它自己或者一个json
        for(var name in obj1){
            console.log(typeof (obj1[name]));
            console.log(obj1[name]);
            if(typeof obj1[name] === "object"){
                obj2[name] = (obj1[name].constructor === Array)?[]:{};//赋值obj2={arr1:[]}
                copy(obj1[name],obj2[name]);
                console.log(obj2[name]);
            }else{
                obj2[name]=obj1[name];//string类型不是对象,直接等于即可,不会发生引用
            }
        }
        return obj2;//[1,2,3,4]
    }
    json2 = copy(json1,json2);//[1,2,3,4]
    json1.arr1.push(666);
    console.log(json1.arr1);//[1, 2, 3, 4, 666]
    console.log(json2.arr1);//[1, 2, 3, 4]
</script>





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值