美文网首页
深浅拷贝

深浅拷贝

作者: w_wx_x | 来源:发表于2019-01-08 13:29 被阅读7次
基础知识
1.数据结构

:只允许在一段进行插入和删除的线性表,是一种 先进后出 的数据结构
:基于 散列算法 的数据结构
队列先进先出 的数据结构
注:
  堆比栈大,栈的速度相对快
  堆内存是无序存储的,根据引用直接获取

2.数据类型

基础数据类型(存储在栈内存中)
  String
  Number
  Boolean
  Undefined
  Null
  Symbol
引用数据类型(存储在堆内存中,再在栈内存中保存一个堆内存中的实际对象引用,引用数据的操作只是对对象引用的操作而不是实际的对象)
  Array
  Object
注:
  基本数据类型:复制时,系统会自动为新的变量在栈内存中分配一个 新的值
  引用数据类型:复制时,会在栈内存中分配一个值,这个值 仅仅是一个地址
        (复制对象和原有对象具有相同的地址值,
         指向堆内存的 同一个对象
  基本数据稳定,相对占用内存小;引用数据类型大小时动态的,无限的

image.png
拷贝
1.深拷贝

目标的完全拷贝,进行深拷贝后,他们 老死不相往来,谁也不影响谁
需层层递归复制对象的所有属性,包括对象的属性的属性的属性...

方式一:手写深拷贝(递归)

// 仅简单的复制对象属性不考虑它的constructor也不考虑函数正则Data等特殊数据类型
function deepCopy(obj){
  if(typeof obj !== "object"){ return ; }
  var str = JSON.stringify(obj);
  return JSON.parse(str)
}

//
function deepCopy(obj){
  var newObj = obj.constructor === Array ? []:{};
  newObj.constructor = obj.constructor;
  if(typeof obj !== "object"){ 
    return ;
  } else if(window.JSON){
    //若需要考虑特殊的数据类型,如正则,函数等,需把这个else if去掉即可
    newObj = JSON.parse(JSON.stringify(obj));
  } else {
    for(var prop in obj){
      if(obj[prop].constructor === RegExp ||obj[prop].constructor === Date){
        newObj[prop] = obj[prop];
      } else if(typeof obj[prop] === 'object'){
        //递归
        newObj[prop] = deepCopy(obj[prop]);
      } else {
        newObj[prop] = obj[prop];
      }
    }
  } 
  return newObj;
}

方式二:jquery.extend([deep],target,object1[,objectN])
    deep:Boolean。true:深拷贝,false:默认,浅拷贝

var object1 = {
  apple:0,
  banana:{
    weight:52,
    price:100
  },
  cherry:97
}
var object2 = {
  banana:{
    price:200
  },
  durian:100
}
$.extend(object1,object2)          // object1 = {"apple":0,"banana":{"price":200},"cherry":97,"durian":100}
$.extend(true,object1,object2)     // object1 = {"apple":0,"banana":{"weight":52,"price":200},"cherry":97,"durian":100}

方式三:JSON对象中的parse和stringify【仅适用于简单的情况,对象包含方法的时候,此方法不可用】

const originArray = [1,2,3,4,5];
const cloneArray = JSON.parse(JSON.stringify(originArray));
console.log(cloneArray === originArray);                     // false

const originObj = {a:'a',b:'b',c:[1,2,3],d:{dd:'dd'}};
const cloneObj = JSON.parse(JSON.stringify(originObj));
console.log(cloneObj === originObj);                         // false
cloneObj.a = 'aa';
cloneObj.c = [1,1,1];
cloneObj.d.dd = 'doubled';
console.log(cloneObj);                                     // {a:'aa',b:'b',c:[1,1,1],d:{dd:'doubled'}};
console.log(originObj);                                    // {a:'a',b:'b',c:[1,2,3],d:{dd:'dd'}};
2.浅拷贝

只复制引用,而未复制真正的值。
只是复制一层引用或对象的每一个属性,不会对这些属性进行递归复制

方式一:普通

var arr = ["One","Two","Three"]; 
var arrto = arr; 
arrto[1] = "test"; 
document.writeln("数组的原始值:" + arr + "<br />");            //Export:数组的原始值:One,test,Three 
document.writeln("数组的新值:" + arrto + "<br />");            //Export:数组的新值:One,test,Three

方式二:concat,slice只是对数组的第一层进行深拷贝

var arr = ["One","Two","Three"];

// concat
var arrtooo2 = arr.concat();
arrtooo2[1] = "set Map To";
document.writeln("数组的原始值:" + arr + "<br />");            // Export:数组的原始值:One,Two,Three
document.writeln("数组的新值:" + arrtooo2 + "<br />");         // Export:数组的新值:One,set Map To,Three

// slice
var arrtoo1 = arr.slice(0);
arrtoo1[1] = "set Map";
document.writeln("数组的原始值:" + arr + "<br />");            // Export:数组的原始值:One,Two,Three
document.writeln("数组的新值:" + arrtoo1 + "<br />");          // Export:数组的新值:One,set Map,Three

方式三:Object.assign()拷贝的是属性值,假如源对象的属性值是一个指向对象的引用,他也只是拷贝那个引用值

var newObj = Object.assign({},originObj)

方式四:手写浅复制

function shadowCopy(obj){
  if(typeof obj!=='object') return;
  var newObj;
  if(obj.constructor === Array){
    newObj = []
  }else{
    newObj = {};
    newObj.constructor = obj.constructor;
  }
  for(var prop in obj){
    if(obj.hasOwnProperty(prop)){
      newObj[prop] = obj[prop];
    }
  }
  return newObj;
}


var arr1 = [0,1,2];
console.log(arr1);                                // [0,1,2]
console.log(shadowCopy(arr1));                    // [0,1,2]

var arr2 = [0,1,2,[3,4,5]],
arr2Copy = shadowCopy(arr2);
console.log(arr2);                                // [0,1,2,[3,4,5]]
console.log(arr2Copy);                            // [0,1,2,[3,4,5]]
arr2Copy[3][0] = 6;
console.log(arr2[3][0]);                         // 6

方式五:...实现的是对象第一层的深拷贝

const originArray = [1,2,3,4,5,[6,7,8]];
const originObj = {a:1,b:{bb:1}};
 
const cloneArray = [...originArray];
cloneArray[0] = 0;
cloneArray[5].push(9);
console.log(originArray);           // [1,2,3,4,5,[6,7,8,9]]
 
const cloneObj = {...originObj};
cloneObj.a = 2;
cloneObj.b.bb = 2;
console.log(originObj);           // {a:1,b:{bb:2}}
总结

=:实现的是浅拷贝,仅拷贝对象的引用值。基础数据类型可以直接使用赋值
Javascript中数组和对象自带的拷贝方法都是"首层浅拷贝"
JSON.stringify实现的是深拷贝,但对目标对象有要求
若想真正的深拷贝,需自行递归

相关文章

  • 2018-08-29

    深浅拷贝 1.根据拷贝内容的不同,分为深浅拷贝 深拷贝:内容...

  • js的深浅拷贝

    js的深浅拷贝可以分为数组的深浅拷贝和对象的深浅拷贝 一、数组的深浅拷贝如果只是简单的将数组中的元素付给另外一个数...

  • Python—浅拷贝与深拷贝

    浅拷贝 深拷贝 深浅拷贝的作用

  • 深浅拷贝

    先来了解一下这些:在js中变量类型基本分为两种:基本数据类型和引用数据类型;基本类型:Underfied Null...

  • 深浅拷贝

    浅拷贝是对一个对象的顶层拷贝。通俗的理解就是:拷贝了引用,并没有拷贝内容。 深拷贝是对于一个对象所有层次的拷贝(递...

  • 深浅拷贝

    深浅拷贝.copy 浅拷贝 这是一个方法,浅拷贝修改可变类型是会将原数据也一块修改 Copy.deepcopy 深...

  • 深浅拷贝

    1:is 和 ==的区别 is 是比较两个引用是否指向了同一个对象(地址引用比较)。== 是比较两个对象是否相等。...

  • 深浅拷贝

    函数的传递,与matlab不同,具有以下特点: 1.直接赋值会带来不同ID,例如,a=2,b=2 2.传递引用赋值...

  • 深浅拷贝

    最近一直被问到深浅拷贝的问题。自己也确实不太清楚怎么回事,现在来研究一下。 什么是深浅拷贝 浅拷贝:指针拷贝,不会...

  • 深浅拷贝

    概念: 浅复制:不拷贝对象本身,仅仅是拷贝指向对象的指针深复制:是直接拷贝整个对象内存到另一块内存中 注意:这里有...

网友评论

      本文标题:深浅拷贝

      本文链接:https://www.haomeiwen.com/subject/jlkvrqtx.html