zoukankan      html  css  js  c++  java
  • js中对象的复制,浅复制(浅拷贝)和深复制(深拷贝)

    在js中,我们经常复制一个对象,复制数据,那么就会有人问了,怎么复制,今天鹏哥就带来js中的复制方法。

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

    堆内存用于存放由new创建的对象,栈内存存放一些基本类型的变量和对象的引用变量。

    至于堆内存和栈内存的区别介绍,你们可以百度看看。

    下面开始讲解复制:

    这种只是简单的变量,内存小,我们直接复制不会发生引用。

    var a=123;
    var b=a;
    a=123456;
    alert(a); //123456
    alert(b); //123
    
    //或者是
    
    var a='afafas';
    var b=a;
    a='fgfdsdsgs';
    alert(a); //fgfdsdsgs
    alert(b); //afafas

    而对于对象这种内存占用比较大的来说,直接让复制的东西等于要复制的,那么就会发生引用,因为这种复制,只是将复制出来的东西的指向指向了要复制的那个东西,简单的说,就是两个都同时指向了一个空间,如果改变其中一个,另一个也会发生变化。这就发生了引用。

    引用只发生在对象的身上:

    var arr1=[1,2,3];
    var arr2=arr1;
    arr1.push(4);
    alert(arr1); //1234
    alert(arr2); //1234
    arr2.push(5);
    alert(arr1); //12345
    alert(arr2); //12345


    那么对于数组,ES6我们复制有新的两种方法,不会发生引用。

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

    var arr1=[1,2,3];
    var arr2=Array.from(arr1);
    arr1.push(4);
    alert(arr1);  //1234
    alert(arr2);  //123
    arr2.push(5);
    alert(arr1);  //1234
    alert(arr2);  //1235

    第二种:...
    var arr1=[1,2,3];
    var arr2=[...arr1];
    arr1.push(4);
    alert(arr1);  //1234
    alert(arr2);  //123
    arr2.push(5);
    alert(arr1);  //1234
    alert(arr2);  //1235

    第二种这个方法也可以用在函数的行参上面。
    function show(...arr1){  //直接来复制arguments这个伪数组,让它变成真正的数组,从而拥有数组的方法。
      alert(arr1); //1234
      arr1.push(5);
      alert(arr1); //12345
    }
    show(1,2,3,4)

    或者是通过循环来复制:
    var arr1=[1,2,3,4];
    var arr2=[];
    for(var i=0; i<arr1.length; i++){
      arr2[i]=arr1[i];
    }
    arr1.push(5);
    arr2.push(6);
    alert(arr1); //12345
    alert(arr2); //12346
    
    //或者是json
    
    var json1={"name":"鹏哥","age":24,"job":"前端开发"};
    var json2={};
    for(var name in json1){
      json2[name]=json1[name];
    }
    alert(JSON.stringify(json1)); //{"name":"鹏哥","age":24,"job":"前端开发"}
    alert(JSON.stringify(json2)); //{"name":"鹏哥","age":24,"job":"前端开发"}
    json1.a=1;
    json2.b=2;
    alert(JSON.stringify(json1)); //{"name":"鹏哥","age":24,"job":"前端开发","a":1}
    alert(JSON.stringify(json2)); //{"name":"鹏哥","age":24,"job":"前端开发","b":2}


    深复制和浅复制最根本的区别在于是否是真正获取了一个对象的复制实体,而不是引用,

    1)深复制在计算机中开辟了一块内存地址用于存放复制的对象,
      2)而浅复制仅仅是指向被复制的内存地址,如果原地址中对象被改变了,那么浅复制出来的对象也会相应改变。

    所谓的浅复制,只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做“(浅复制)浅拷贝”。

    看例子:

    var json1 = {"a":"李鹏","arr1":[1,2,3]}
    function copy(obj1) {
        var obj2 = {};
        for (var i in obj1) {
          obj2[i] = obj1[i];
        }
        return obj2;
    }
    var json2 = copy(json1);
    json1.arr1.push(4);
    alert(json1.arr1);  //1234
    alert(json2.arr1)  //1234

    而深复制的话,我们要求复制一个复杂的对象,那么我们就可以利用递归的思想来做,及省性能,又不会发生引用。
    看例子:
    var json1={"name":"鹏哥","age":18,"arr1":[1,2,3,4,5],"string":'afasfsafa',"arr2":[1,2,3,4,5],"arr3":[{"name1":"李鹏"},{"job":"前端开发"}]}; var json2={}; function copy(obj1,obj2){ var obj2=obj2||{}; //最初的时候给它一个初始值=它自己或者是一个json for(var name in obj1){ if(typeof obj1[name] === "object"){ //先判断一下obj[name]是不是一个对象 obj2[name]= (obj1[name].constructor===Array)?[]:{}; //我们让要复制的对象的name项=数组或者是json copy(obj1[name],obj2[name]); //然后来无限调用函数自己 递归思想 }else{ obj2[name]=obj1[name]; //如果不是对象,直接等于即可,不会发生引用。 } } return obj2; //然后在把复制好的对象给return出去 } json2=copy(json1,json2) json1.arr1.push(6); alert(json1.arr1); //123456 alert(json2.arr1); //12345

    以上,结束。


    转自:https://www.jianshu.com/p/0d7bd31ccf43

  • 相关阅读:
    【Linux】【Services】【SaaS】Docker+kubernetes(11. 构建复杂的高可用网络)
    【Linux】【Services】【SaaS】Docker+kubernetes(10. 利用反向代理实现服务高可用)
    socketserver.py
    Python 字符中文坑
    H3C对接华为S5700s---配置链路聚合
    format使用
    python 登入接口
    python 多级菜单
    Windows 下安装MongoDB
    Gerrit 服务器安装插件
  • 原文地址:https://www.cnblogs.com/nxmxl/p/12340109.html
Copyright © 2011-2022 走看看