• 二. JavaScript 数组 和 对象 的深浅拷贝


    前提:原始数据类型和对象类型赋值时的差异

      JavaScript的数据类型分为:原始数据类型和对象类型。二者在内存中存放的方式不同,导致了其赋值时差异。分别举个栗子 

    1.原始数据类型:Undefined、Null、Boolean、Number以及String。

    2.对象类型

      var x = 1;
      var y = x;  //y获得了和x同样的值
      y = 2;
      console.log(x);  // 1
    
      var m = [1,2]; //m存放的是指向[1,2]这个数组对象的引用地址
      var n = m; //n也获得 [1,2]数组对象的引用地址
      n[0] = 3;
      console.log(m);  //[3,2] 

    浅拷贝?

      顾名思义,浅拷贝就是流于表面的拷贝方式;当属性值为对象类型时,只拷贝了对象数据的引用,导致新旧数据没有完全分离,还会互相影响。再举个栗子···

    var array1 = ['a',1,true,{name:'lei',age:18}];
    var array2 = array1.concat();   //注意不能直接=,不然直接数组对象,没有原始类型了
    array2[0] = 'b';               //array1[0]是原始数据类型 所以是直接赋值的
    array2[3].name = 'zhang';      //array1[3]是对象数据类型 所以拷贝的是对象的引用,其实还是和原数组使用同一对象
    console.log(array1);         //  ['a',1,true,{name:'zhang',age:18}]

    如何实现浅拷贝

    1. 上栗中的  array.concat()或者array.slice() 是特殊的实现数组浅拷贝的方式。
    2. 如何自己实现呢?遍历对象/数组的每个属性,然后赋值给一个新的对象不就行了么,如下实现
    //实现浅拷贝
      function shallowCopy( target ){
        if(typeof target !== 'object') return ;
        //判断目标类型,来创建返回值
        var newObj = target instanceof Array ? [] : {};
        for(var item in target){
          //只复制元素自身的属性,不复制原型链上的
          if(target.hasOwnProperty(item)){
            newObj[item] = target[item]
          }
        }
        return newObj
      }
    
      var test = [1,'a',{name:'lei',age:18}];
      var copy = shallowCopy(test);
      console.log(copy[2].name);   //lei
    
      copy[0] = 0;
      copy[2].name = 'zhang';
      console.log(test[0]);        //1       原数据不变
      console.log(test[2].name);   //zhang   原数据也被修改

    深拷贝及其实现

      从浅拷贝解释基本可以明白,深拷贝就是 ‘完全’拷贝,拷贝之后新旧数据完全分离,不再共用对象类型的属性值,不会互相影响。

    //实现深拷贝
    function deepCopy( target ){
      if(typeof target !== 'object') return ;
      //判断目标类型,来创建返回值
      var newObj = target instanceof Array ? [] : {};
    
      for(var item in target){
        //只复制元素自身的属性,不复制原型链上的
        if(target.hasOwnProperty(item)){
          newObj[item] = typeof target[item] == 'object' ? deepCopy(target[item]) : target[item]  //判断属性值类型
        }
      }
      return newObj
    }
    
    //测试
    var test = [1,'a',{name:'lei',age:18}];
    
    var copy2 = deepCopy(test);
    copy[0] = 0;
    copy2[2].name = 'zhang'
    console.log(test);         //[1,'a',{name:'lei',age:18}]  未受到影响
  • 相关阅读:
    遍历切片slice,结构体struct,映射map,interface{}的属性和值
    [转]Go语言string,int,int64 ,float之间类型转换方法
    [转] golang中struct、json、map互相转化
    [转]Jupyter默认目录和默认浏览器修改
    sublime text3输出窗口中文显示乱码问题解决方案
    Oracle 在SQL语句中如何获取系统当前时间并进行操作
    eclipse调试的时候怎么后退?
    外部无法访问虚拟机8088和50070端口
    hadoop启动后jps查不到namenode的解决办法
    Java给整数部分的字符串加上千分位分隔符
  • 原文地址:https://www.cnblogs.com/hy-space/p/8945595.html
Copyright © 2020-2023  润新知