首页 > 编程语言 >JavaScript 浅拷贝和深拷贝详解

JavaScript 浅拷贝和深拷贝详解

时间:2023-07-31 17:37:26浏览次数:49  
标签:console name 对象 JavaScript 详解 let 数组 拷贝

一、基本数据类型和引用数据类型

基本数据类型:1.Number(数字类型) 2.String(字符串类型) 3. Boolean(布尔类型) 4. Null(空类型) 5.Undefined(未定义类型) 6. Symbol(符号类型)

引用数据类型: Object(对象类型):表示一组无序的键值对,例如 {name: '张三', age: 18}。

基本数据类型是简单的数据类型,它们的值都是直接存储在变量中的,而引用数据类型则是保存在内存中的对象,变量保存的是对象的地址。因此,在比较两个引用数据类型的值时,比较的是它们的引用地址,而非内容。

二、深拷贝和浅拷贝

浅拷贝: 创建一个新对象或数组,新对象或数组的内部元素的引用和原对象或数组相同,即新对象或数组和原对象或数组共享同一块内存地址。当原对象或数组改变时,新对象或数组也会跟着改变。

var a = 10;
var b = a;
a = 100;
console.log(b);  // 10

深拷贝: 创建一个新对象或数组,新对象或数组的内部元素的引用和原对象或数组不同,即新对象或数组和原对象或数组没有共享同一块内存地址。当原对象或数组改变时,新对象或数组不会跟着改变。

var a = [10,20,30];
var b = a;
a[0] = 100;
console.log(b);  // [100,20,30]

三、实现数组和对象深拷贝

1、针对于数组实现深拷贝,可以使用slice和concat方法,还可以使用ES6的展开运算符

 const Arr = ["one", "two", "three"];
 const fxArr = Arr.slice(0);
 fxArr[1] = 'love'
 console.log(Arr); // ["one", "two", "three"]

 const Arr = ["one", "two", "three"];
 const fxArr = Arr.concat(0);
 fxArr[1] = 'love'
 console.log(Arr); //  ["one", "two", "three"]

 const  Arr = ["one", "two", "three"];
 const  fxArr = [...Arr]
 fxArr[1] = 'love'
 console.log(Arr); // ["one", "two", "three"]

2、针对于对象实现拷贝呢,可以使用以下几种方案?

----------------------------使用对象API实现深拷贝-----------------------

 let obj1 = {
       name:"张三",
       age:18
 }
 let obj2 =  JSON.parse(JSON.stringify(obj1));
 obj2.name="李四"
 console.log(obj1);

----------------------------对象一个一个赋值-----------------------

 let obj1 = {
       name:"ruirui",
       age:18
   }
 let obj2 = {}
 obj2.name = obj1.name;
 obj2.age = obj1.age;
 obj2.name = 'shasha'
 console.log(obj1); // {name: "ruirui", age: 18}

-----------------------------ES6扩展运算符---------------------------

let obj1 = {
       name:"ruirui",
       age:18
   }
let obj2 = {...obj1}

--------------------------对象遍历赋值------------------------------

 var p = {
        "id":"007",
        "name":"张三"
 }
 var p2 = {};
 for (let key in p) {
   p2[key] = p[key];
 }
 p2.name = '李四'
 console.log(p); // {id: "007", name: "张三"}

3、上面属于一层,如果含有多层,对象遍历赋值只能外层对象是深拷贝的,内层对象是浅拷贝

 let p = {
        "id":"007",
        "name":"刘德华",
        "books":newArray("三国演义", "红楼梦", "水浒传")//这是引用类型
 }
 function copy(obj){
	   var newobj = {};
	   for(var k in obj){
		   newobj[k] = obj[k]
	   }
	   return newobj
 }

发现实现不了上述要求:下面提供一种递归的思路来进行解决该问题。

 var p = {
        "id":"007",
        "name":"刘德华",
        "wife": {
            "id":"008",
            "name":"刘德的妻子",
            "address": {
                "city":"北京",
                "area":"海淀区"
            }
        }
 }

//编写函数

function copyObj(obj) {
        let newObj = {};
        for (let key in obj) {
            if (typeof obj[key] == 'object') {
             newObj[key] = copyObj(obj[key]); //如:key是wife,引用类型,那就递归**
            } else {
             newObj[key] = obj[key]; //基本类型,直接赋值**
            }
        }
        return newObj;
}
let pNew = copyObj(p);
pNew.wife.name = "张三疯";
pNew.wife.address.city = "香港";
console.log(pNew);
console.log(p);

运行效果 image-20230731164408301.png 需要说明的是,在实际开发中,需要根据具体情况选择适合的拷贝方法。

标签:console,name,对象,JavaScript,详解,let,数组,拷贝
From: https://blog.51cto.com/u_16203259/6910443

相关文章

  • unsigned char数组拷贝数据段,置0数据段,未越界方法
    需要注意的是,自己去写C语言场景下数组的拼接,得不偿失,因为涉及到了数组的拼接,就会有动态分配内存,目前C语言是没有这个功能的;自己写会容易内存报错;因此,在涉及到C语言数组时,最好是只有拷贝,赋值等操作,在一开始确定数组时,把内存分配大一些;这里主要对内存越界的地方做个封装;然后可以实......
  • java 代理(静态代理、动态代理的不同实现)详解及示例
    文章目录一、代理构成1、代理介绍2、应用场景介绍二、静态代理1、示例1)、售票服务2)、售票3)、代售点服务4)、静态代理实现1、maven依赖2、实现三、动态代理1、InvocationHandler角色2、InvocationHandler的作用3、JDK的动态代理创建机制----通过接口1)、Proxy2)、InvocationHandler3)......
  • javascript实现浏览器端大文件分块上传
    ​ 以ASP.NETCoreWebAPI 作后端 API ,用 Vue 构建前端页面,用 Axios 从前端访问后端 API,包括文件的上传和下载。 准备文件上传的API #region 文件上传  可以带参数        [HttpPost("upload")]        publicJsonResultuploadProject(I......
  • Spring IOC实现原理详解之IOC体系结构设计 : 关于bean的生成我自己的理解;
    1、系统根据bean的配置信息(xml文件,groovy等),经过资源加载、解析配置后生成了一个关于bean的容器。2、bean容器会根据配置信息生成一个bean实例;3、将bean实例 和 一些其他配置信息生成的一些特殊的bean实例 都放入到bean的容器中;4、其他的类需要调用这些bean的时候,根据申......
  • HTTP协议详解
    HTTP协议详解我们在进行两台主机进行数据交互的时候,会遇到很多问题。如数据丢包,数据重复,数据完整性校验,数字转换模拟信号,信号衰竭等。为了简化网络的复杂度,网络通信的不同方面被分解为多层次结构,每一层只与紧挨着是上层或者下层交互,将网络分层,这样就可以修改,甚至替换某一层的......
  • 【补充】on_delete的参数详解
    【补充】on_delete的参数详解models.CASCADE(级联删除):当删除与该字段关联的对象时,所有相关的对象将被级联删除。例如,如果一个出版社对象被删除了,与该出版社相关联的所有图书对象也会被删除。models.SET_DEFAULT:(设置为默认值):当删除与该字段关联的对象时,该字段的值将设置为字段......
  • python 拷贝文件
    如何使用Python拷贝文件作为一名经验丰富的开发者,我很乐意教给你如何在Python中实现文件的拷贝操作。下面是整个过程的步骤:步骤描述1打开源文件2读取源文件内容3创建目标文件4将源文件内容写入目标文件5关闭文件现在我们逐步来看每一步应该如何实......
  • 【Web开发指南】如何用MyEclipse进行JavaScript开发?
    由于MyEclipse中有高级语法高亮显示、智能内容辅助和准确验证等特性,进行JavaScript编码不再是一项繁琐的任务。MyEclipsev2023.1.1离线版下载MyEclipse技术交流群:742336981欢迎一起进群讨论JavaScript项目在MyEclipse 2021及以后的版本中,大多数JavaScript支持都是开箱即用......
  • spring RestTemplate用法详解
    前面介绍过spring的MVC结合不同的view显示不同的数据,如:结合json的view显示json、结合xml的view显示xml文档。那么这些数据除了在WebBrowser中用JavaScript来调用以外,还可以用远程服务器的Java程序、C#程序来调用。也就是说现在的程序不仅在BS中能调用,在CS中同样也能调用,不过你需要......
  • 工业机器人坐标系详解(基于六轴串联机器人和SCARA机器人)
    工业机器人的坐标系机器人的坐标系是重中之重,它是理解机器人运动的基础。机器人所有运动的点位都是建立在坐标系的基础之上,所以如果坐标系不理解,那么就很难真实了解机器人是如何运动的。什么是坐标系?我们需要移动机器人来工作,但是如何让机器人移动?当然我们可以单独控制机器人的......