美文网首页
js中对象的复制,浅复制(浅拷贝)和深复制(深拷贝)

js中对象的复制,浅复制(浅拷贝)和深复制(深拷贝)

作者: 虚幻的锈色 | 来源:发表于2017-03-07 14:13 被阅读23637次

在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

以上,结束。

相关文章

  • java 对象的拷贝

    拷贝:即复制 对象拷贝:即对象复制 java 对象拷贝分类:浅拷贝、深拷贝 java 对象的浅拷贝和深拷贝针对包含...

  • 浅拷贝和深拷贝

    本文参考:JavaScript中的浅拷贝和深拷贝js 深拷贝 vs 浅拷贝深入剖析 JavaScript 的深复制...

  • JS中对象的复制

    JS中的对象复制分为两种情况:深拷贝和浅拷贝。深拷贝和浅拷贝的区别在于对数组和对象的拷贝,对它们拷贝时浅拷贝只是拷...

  • 面试题iOS

    面试blog 1、深拷贝浅拷贝:浅拷贝就是拷贝对象的指针,而不复制引用对象本身;深拷贝就是拷贝引用对象本身;浅复制...

  • python中的浅拷贝和深拷贝

    浅拷贝和深拷贝: 浅拷贝 shallow copy 浅拷贝是指在对象复制过程中,只复制一层变量,不会复...

  • 前端笔记(二) 对象的深浅拷贝,函数的防抖与节流,函数柯里化 ,

    对象的深浅拷贝 对象的深拷贝与浅拷贝的区别: 浅拷贝:仅仅复制对象的引用, 而不是对象本身。 深拷贝:把复制的对象...

  • iOS全解11:特殊问题

    1、浅拷贝和深拷贝的区别? 浅拷贝:只复制指向对象的指针,指针指向同一个地址,而不复制引用对象本身。深拷贝:复制引...

  • 浅拷贝和深拷贝

    浅拷贝和深拷贝都是只针对Object,Array这样的复杂对象。浅拷贝只复制一层对象的属性,而深拷贝则是递归复制了...

  • 浅拷贝与深拷贝NSMutableCopy、NScopy

    1.浅拷贝和深拷贝的区别 浅拷贝只是复制对象本身,对象属性包含的对象不复制,不产生新对象,直接指向原有对象。 深拷...

  • iOS 深拷贝,浅拷贝

    深拷贝与浅拷贝 浅拷贝:浅拷贝并不拷贝对象本身,只是对指向对象的指针进行拷贝,并没有进行真正的复制,而是复制的对象...

网友评论

      本文标题:js中对象的复制,浅复制(浅拷贝)和深复制(深拷贝)

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