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

原文地址:https://www.cnblogs.com/nxmxl/p/12340109.html

时间: 2024-10-27 04:05:32

js中对象的复制,浅复制(浅拷贝)和深复制(深拷贝)的相关文章

js中对象的浅拷贝和深拷贝的区别

js中对象的浅拷贝和深拷贝的区别 浅度拷贝:复制一层对象的属性,并不包括对象里面的为引用类型的数据,当改变拷贝的对象里面的引用类型时,源对象也会改变. 深度拷贝:重新开辟一个内存空间,需要递归拷贝对象里的引用,直到子属性都为基本类型.两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性. 数据的类型: 一般数据(值传递):字符,数值,布尔,undefined 拷贝(复制)时,传递的是值,修改新数据,不会影响老数据 复杂数据(引用传递):对象 拷贝(复制)时,传递的是内存地址的

OpenCv学习笔记(四)--Mat基本图像容器Mat对象信息头,矩阵体的创建,深复制,浅复制详解

1--我们知道Mat是一个图像容器类,这个数据结构由两部分组成: 1--矩阵头--即class Mat类所实例化的类对象所开辟的空间里面存储的数据---就是这个矩阵的信息,当我们以 Mat object;这样声明类对象的时候,也仅仅是创建了一个Mat的信息头,并没有创建矩阵体,也就是说,我们并 没有给将要存储的图像开辟相应的空间 2--矩阵头--包含: 1--矩阵的尺寸----比如---class Mat这个类中的----数据成员rows,cols---就可以指定图像的尺寸 2--存储方法---

.net中对象序列化技术浅谈

.net中对象序列化技术浅谈 2009-03-11 阅读2756评论2 序列化是将对象状态转换为可保持或传输的格式的过程.与序列化相对的是反序列化,它将流转换为对象.这两个过程结合起来,可以轻松地存储和传输数 据.例如,可以序列化一个对象,然后使用 HTTP 通过 Internet 在客户端和服务器之间传输该对象.反之,反序列化根据流重新构造对象.此外还可以将对象序列化后保存到本地,再次运行的时候可以从本地文件 中“恢复”对象到序列化之前的状态.在.net中有提供了几种序列化的方式:二进制序列化

[转]JS中对象与字符串的互相转换

原文地址:http://www.cnblogs.com/luminji/p/3617160.html 在使用 JSON2.JS 文件的 JSON.parse(data) 方法时候,碰到了问题: throw new SyntaxError('JSON.parse'); 查询资料,大概意思如下: JSON.parse方法在遇到不可解析的字符串时,会抛出SyntaxError异常. 即:JSON.parse(text, reviver),This method parses a JSON text t

原生 JS 中对象相关 API 合集

https://juejin.im/entry/58f8a705a0bb9f0065a4cb20 原文链接:https://microzz.com/2017/04/20/jsobject/ 原生 JavaScript 中对象相关 API 合集 - 对象篇.现在 jQuery 已经没有那么有优势了,原生 JS 赶紧学起来... -- 由microzz分享 Microzz [email protected] 主页 文章 标签 GitHub 关于我 掘金专栏 SegmentFault Vue音乐播放器

探究JS中对象的深拷贝和浅拷贝

深拷贝和浅拷贝的区别 在讲深拷贝和浅拷贝的区别之前,回想一下我们平时拷贝一个对象时是怎么操作的?是不是像这样? var testObj1 = {a: 1, b:2}, testObj2=testObj1; testObj1.a = 7; console.log(testObj1); //{a: 7, b:2} console.log(testObj2); //{a: 7, b:2} 发现问题了吗?当testObj1变化时,testObj2相应的属性跟着变化了.这就是属于浅拷贝了,而所谓的深拷贝就

小程序 js中获取时间new date()的用法(网络复制过来自用)

js中获取时间new date()的用法 获取时间: 1 var myDate = new Date();//获取系统当前时间 获取特定格式的时间: 1 myDate.getYear(); //获取当前年份(2位) 2 myDate.getFullYear(); //获取完整的年份(4位,1970-????) 3 myDate.getMonth(); //获取当前月份(0-11,0代表1月) 4 myDate.getDate(); //获取当前日(1-31) 5 myDate.getDay();

A.JS中对象的简单介绍

JS中的对象实际上是一个包含属性和方法的一个特殊的数据集合.调用的时候用(.)来进行调用.object.property;object.method.为了加深理解,我们设置一个person对象,他有age,sex属性:有sleep(),eat()方法.那么当我们要使用person对象时,首先,需要实例化一个对象,利用new关键字,比如: var bob = new person; 上面的语句就是实例化了一个person对象,bob.他有person对象的所有属性和方法.可以利用(.)来进行对属性

js 中对象的简单创建和继承

对象的简单创建 1.通过对象直接量创建 比如 var obj = {}; 2.通过new 创建 比如 var obj = new Object(); // 相当于var obj = {}; var arr = new Array(); 3.使用 Object.create() 这个方法有两个参数,第一个参数是这个对象的原型,第二个参数用以对对象的属性进行进一步描述(可选) var obj = Object.create({x:1}); var obj1 = Object.create(null)