深拷贝 订阅
一个引用对象一般来说由两个部分组成:一个具名的Handle,也就是我们所说的声明(如变量)和一个内部(不具名)的对象,也就是具名Handle的内部对象。它在Manged Heap(托管堆)中分配,一般由新增引用对象的New方法是进行创建。深拷贝是指源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。举个例子,一个人名叫张三,后来用他克隆(假设法律允许)了另外一个人,叫李四,不管是张三缺胳膊少腿还是李四缺胳膊少腿都不会影响另外一个人。比较典型的就是Value(值)对象,如预定义类型Int32,Double,以及结构(struct),枚举(Enum)等。 展开全文
一个引用对象一般来说由两个部分组成:一个具名的Handle,也就是我们所说的声明(如变量)和一个内部(不具名)的对象,也就是具名Handle的内部对象。它在Manged Heap(托管堆)中分配,一般由新增引用对象的New方法是进行创建。深拷贝是指源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。举个例子,一个人名叫张三,后来用他克隆(假设法律允许)了另外一个人,叫李四,不管是张三缺胳膊少腿还是李四缺胳膊少腿都不会影响另外一个人。比较典型的就是Value(值)对象,如预定义类型Int32,Double,以及结构(struct),枚举(Enum)等。
信息
要    求
复制对象空间和资源
特    点
源对象与拷贝对象互相独立
有关术语
拷贝构造函数
中文名
深拷贝
学    科
软件工程
外文名
deep copy
深拷贝简介
如果在类中没有显式地声明一个拷贝构造函数,那么,编译器将会自动生成一个默认的拷贝构造函数,该构造函数完成对象之间的位拷贝。位拷贝又称浅拷贝,浅拷贝会带来数据安全方面的隐患。在进行赋值之前,为指针类型的数据成员另辟了一个独立的内存空间,实现真正内容上的拷贝 [1]  。这种拷贝称为深拷贝。深拷贝有两种方式实现:层层clone的方法和利用串行化来做深拷贝。层层clone的方法:在浅拷贝的基础上实现,给引用类型的属性添加克隆方法,并且在拷贝的时候也实现引用类型的拷贝。此种方法由于要在多个地方实现拷贝方法,可能会造成混论。利用串行化来做深拷贝:为避免复杂对象中使用clone方法可能带来的换乱,可以使用串化来实现深拷贝。先将对象写到流里,然后再从流里读出来。
收起全文
精华内容
下载资源
问答
  • 深拷贝

    2019-02-11 15:28:20
    1. JS 中拷贝对象分为浅拷贝和深拷贝 浅拷贝 : 拷贝引用 深拷贝 : 拷贝里面的数据成新的对象 2. 常规做法 递归 , 简单实现方式如下: var a = {name: "xiaoming"} var b = JSON.parse(JSON....

    1.  JS 中拷贝对象分为浅拷贝和深拷贝

    浅拷贝 : 拷贝引用

    深拷贝 : 拷贝里面的数据成新的对象

    2.  常规做法  递归 ,  简单实现方式如下:

    var a = {name: "xiaoming"}
    var b = JSON.parse(JSON.stringify(a))
    
    // b 就是对 a 的一个深拷贝

    当对象中包含 undefined函数以及 symbol 值的时候,在 JSON.stringify() 序列化过程中会被忽略,所以需要避免在包含上述值的源对象中采用这种拷贝方式

    展开全文
  • javascript 数组以及对象的深拷贝(复制数组或复制对象)的方法前言在js中,数组和对象的复制如果使用=号来进行复制,那只是浅拷贝。如下图演示: 如上,arr的修改,会影响arr2的值,这显然在绝大多数情况下,并...

    javascript 数组以及对象的深拷贝(复制数组或复制对象)的方法

    前言

    在js中,数组和对象的复制如果使用=号来进行复制,那只是浅拷贝。如下图演示:

    如上,arr的修改,会影响arr2的值,这显然在绝大多数情况下,并不是我们所需要的结果。
    因此,数组以及对象的深拷贝就是javascript的一个基本功了。

    评论中有很多人说我误导大家。说这些都是浅拷贝。我不做过深的阐述,本文中涉及到的都是比较浅显的内容。诸位请根据自己的需要以及情况自行判断和理解。

    数组的深拷贝

    条条大道通罗马,实现数组的深拷贝,是有好几种方法的。举例如下:

    for 循环实现数组的深拷贝

    for循环是非常好用的。如果不知道高级方法,通过for循环能够完成我们大多数的需求。

    var arr = [1,2,3,4,5]
    var arr2 = copyArr(arr)
    function copyArr(arr) {
    	let res = []
    	for (let i = 0; i < arr.length; i++) {
    	 res.push(arr[i])
    	}
    	return res
    }
    

    如上,通过对数组的for循环,即可实现对数组的深拷贝了。

    slice 方法实现数组的深拷贝

    这个代码实现非常简单。原理也比较好理解,他是将原数组中抽离部分出来形成一个新数组。我们只要设置为抽离全部,即可完成数组的深拷贝。代码如下:

    var arr = [1,2,3,4,5]
    var arr2 = arr.slice(0)
    arr[2] = 5
    console.log(arr)
    console.log(arr2)
    

    运行结果如下:

    更多 slice 内容请访问 w3school JavaScript slice 方法

    concat 方法实现数组的深拷贝

    这个代码也非常简单,原理更加粗暴。它是用于连接多个数组组成一个新的数组的方法。那么,我们只要连接它自己,即可完成数组的深拷贝。代码如下:

    var arr = [1,2,3,4,5]
    var arr2 = arr.concat()
    arr[2] = 5
    console.log(arr)
    console.log(arr2)
    

    运行结果如下:

    更多 concat 内容请访问 w3school JavaScript concat 方法

    2017年10月31日补充:ES6扩展运算符实现数组的深拷贝

    OK,以上之前讲的方法全部过时了,用下面的方法实现数组的深拷贝是最简单的。

    var arr = [1,2,3,4,5]
    var [ ...arr2 ] = arr
    arr[2] = 5
    console.log(arr)
    console.log(arr2)
    

    运行结果如下:

    ES6扩展运算符实现数组的深拷贝

    对象的深拷贝

    对象的深拷贝相比数组也没有困难许多,列举两个方法。

    万能的for循环实现对象的深拷贝

    在很多时候,for循环能够解决大问题。

    var obj = {
      name: 'FungLeo',
      sex: 'man',
      old: '18'
    }
    var obj2 = copyObj(obj)
    function copyObj(obj) {
      let res = {}
      for (var key in obj) {
        res[key] = obj[key]
      }
      return res
    }
    

    转换成json再转换成对象实现对象的深拷贝

    上面的代码实在是比较长,所以,用一个更暴力的方法吧!代码如下:

    var obj = {
      name: 'FungLeo',
      sex: 'man',
      old: '18'
    }
    var obj2 = JSON.parse(JSON.stringify(obj))
    

    这个原理没什么好解释的,实在是够简单粗暴的啦!

    2017年10月31日补充: 扩展运算符实现对象的深拷贝

    var obj = {
      name: 'FungLeo',
      sex: 'man',
      old: '18'
    }
    var { ...obj2 } = obj
    obj.old = '22'
    console.log(obj)
    console.log(obj2)
    

    运行结果如下:

    扩展运算符实现对象的深拷贝

    小结

    数组和对象的深拷贝是js中最常见的应用。理解各种方法是必须的。希望对大家有所帮助。
    本文中并没有对异常进行处理,主要在讲原理。更多的数组以及对象的操作方法,可以参考lodash的源码,查看它的源码可以让你的js基础变得非常牢固。我也在学习中。

    2017年10月31日补充,使用es6提供的扩展运算符的方法实现深拷贝,简单,高效。并且,对象的深拷贝不会像使用 JSON 方法深拷贝一样,丢失函数等信息,只能用来深拷贝 JSON 数据格式的对象。推荐大家使用。

    补充一个数组去重的方法

    function dedupe(array) {
      return [...new Set(array)]
    }
    var arr = [1,2,2,3,3,4,4,5,5]
    console.log(dedupe(arr))
    

    运行结果如下:

    JS数组去重的方法

    2021年03月29日 补充

    这里说的深拷贝,都是指一维的数组和对象的深拷贝。鉴于评论中多人指出,这些是浅拷贝,我本来不想回应,但是提出这个观点的人很多,因此我在这边回应一下。

    浅拷贝的概念不重复了,上文中已经说明。文章中的多种方法,均不是浅拷贝,只是是否支持多维数据而已。而在绝大多数场景下,文中的方法是适用的。

    想要简便的支持多维数据的深拷贝,可以直接适用 JSON 方式。或适用 lodash 工具实现。

    版权申明:本文由FungLeo原创,允许转载,但转载必须附注首发链接。谢谢。

    展开全文
  • 手写深拷贝深拷贝理解

    千次阅读 2021-03-31 17:16:46
    手写深拷贝深拷贝理解 前言 浅拷贝与深拷贝的关系 为什么使用深拷贝深拷贝是干什么的? 浅拷贝 与深拷贝相对应的就是浅拷贝,浅拷贝就是直接赋值;在很多情况下我们都需要给变量赋值,给内存地址赋予一个值,...

    手写深拷贝及深拷贝理解

    前言

    1. 浅拷贝与深拷贝的关系
    2. 为什么使用深拷贝,深拷贝是干什么的?

    浅拷贝

    与深拷贝相对应的就是浅拷贝,浅拷贝就是直接赋值;在很多情况下我们都需要给变量赋值,给内存地址赋予一个值,而在赋值引用类型时,只是共享一个内存区域,导致赋值的时候,还跟之前的值保持一至性。

    	var text1 = {
            a:1,
            b:2
        }
        var text2 = text1
        text2.a = 2
    
        console.log(text1.a) // 2
        console.log(text2.a) // 2
    

    就如上面代码中直接给 text2 赋值 text1 只要改变 text2 的值,那么 text1 的值也会改变,那么这就要使用到我们的深拷贝,深拷贝就是给变量新建一个堆内存空间利用递归把数据赋值过去。

    正文

    要使用深拷贝那么就得先判断数据类型,确保是引用类型,因为数据类型不需要。

    var obj = {
        name: '三石',
        age: '20',
        loveColor: 'black',
        hobby: {
          game: 'LOL',
          movement: 'running'
        },
        game:['CF',"CS"]
      }
      
      var newObj = deepClone(obj)
      newObj.wocao[0]= "哈哈哈"
      console.log(obj)
      console.log(newObj)
    
    	//深拷贝
      function deepClone(obj) {
        // 判断obj是不是个对象或者是不是undefined 
        //如果obj不是个对象或者是 undefined 或 null 直接进行 return
        if (typeof obj !== 'object' || obj == null) {
          return obj
        }
        // 初始化一个变量返回结果
        let result
        // 判断obj的类型  然后给result一个一样的数据类型额
        if (obj instanceof Array) {
          result = []
        } else {
          result = {}
        }
        // 利用for in 遍历obj
        for (let key in obj) {
          if (obj.hasOwnProperty(key)) {
          // 下面这个判断可加可不加 看情况  如果死循环的话就加上
            	 // 判断obj【key】是否存在  并且还是引用类型
            if(obj[key] && typeof obj[key] === 'object'){
              result[key] = deepClone(obj[key])
            }else{
              result[key] = obj[key]
            }
          }
        }
        return result
      }
    

    小结
    这只是es5的深拷贝写法,es6跟这个是有些差异,并且这只是深拷贝中的递归的写法。

    展开全文
  • dict2 = dict1.copy() #浅拷贝 拷贝一级对象,但是如果字典里有个列表,改变dict1中这个列表的值的时候,dict2相应改变,可以自己递归实现深拷贝 import copy dict2 = copy.deepcopy(dict1)#深拷贝所有级别的对象都...

    python字典 直接赋值 copy deepcopy

    dict2 = dict1 #对象的引用
    dict2 = dict1.copy() #浅拷贝 拷贝一级对象,但是如果字典里有个列表,改变dict1中这个列表的值的时候,dict2相应改变,可以自己递归实现深拷贝
    import copy
    dict2 = copy.deepcopy(dict1)#深拷贝所有级别的对象都拷贝
    
    
    浅拷贝只拷贝父对象的意思
    a = {1: [1,2,3]}
    b = a.copy() #a, b分别为({1: [1, 2, 3]}, {1: [1, 2, 3]})
    a[1].append(4) #a, b分别为({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]})

    OpenCV mat 直接赋值//Mat image1(image) ;//仅是创建了Mat的头部分,image1与image共享数据区

    cv::Mat image;
    cv::Mat image1(image) ;//仅是创建了Mat的头部分,image1与image共享数据区
    cv::Mat image1 = image ;//仅是创建了Mat的头部分,image1与image共享数据区  
    cv::Mat image1 = image.clone() ;//深拷贝,把image中的所有信息拷贝到image1中
    cv::Mat image1;
    image.copyTo(image1) ;//拷贝image的数据区到image1中,在拷贝数据前会有一步:image1.create(this->size , this->type)
    
    //注意 cv::Mat 作为函数参数,无论写不写& ,看似传值或者传引用这种方式,原图都会发生改变,不使用clone或者copyto或者手动赋值,都不是深拷贝,都共享数据区

    c++ 拷贝构造函数的浅拷贝和深拷贝

    c++中类对象的默认拷贝构造函数是浅拷贝,类a=类b,两个类的成员变量指向同一块内存,如果类b析构了之后,类a的成员变量还指向原来那块内存,就会有野指针的问题,会出错。

    想要深拷贝,应该自己自定义拷贝构造函数,为对应的成员变量开辟新空间。这才是好的编程习惯。

    //深拷贝的例子
    class Example{
    public:
        Example(int num, char* str) {
            num_ = num;
            str_ = new char[num];
            strcpy(str_, str);
        }
        Example(const Example& e) {
            num_ = e.num;
            str_ = new char(num_);
            if(str_ != 0)
                strcpy(str_, e.str);
        }
        ~Example(){
            delete str_;
        }
    
    private:
        int num_;
        char* str_;
    }
    展开全文
  • 一篇文章彻底搞懂浅拷贝和深拷贝

    万次阅读 多人点赞 2018-07-16 16:36:32
    强烈推荐30个原生JavaScript的demo,包括canvas时钟特效、自定义视频...【javascript】详解javaScript的深拷贝 目录 浅谈深拷贝和浅拷贝 深拷贝和浅拷贝的区别 为什么要使用深拷贝深拷贝的要求程度...
  • Java 深拷贝 和 浅拷贝 clone

    万次阅读 2019-11-27 16:15:22
    关于Java的深拷贝和浅拷贝,简单来说就是创建一个和已知对象一模一样的对象。可能日常编码过程中用的不多,但是这是一个面试经常会问的问题,而且了解深拷贝和浅拷贝的原理,对于Java中的所谓值传递或者引用传递将会...
  • 终于弄清楚JS的深拷贝和浅拷贝了-读这一篇就够了

    万次阅读 多人点赞 2018-07-27 17:22:14
    今天,CVTE面试官问了深拷贝和浅拷贝的问题 我的回答是:浅拷贝是拷贝了对象的引用,当原对象发生变化的时候,拷贝对象也跟着变化;深拷贝是另外申请了一块内存,内容和原对象一样,更改原对象,拷贝对象不会发生...
  • 深拷贝和浅拷贝

    万次阅读 多人点赞 2019-05-12 17:28:52
    深拷贝和浅拷贝的知识涉及到堆栈的概念。 堆栈的概念: 基本类型: 名值存储在栈内存中,例如: let a = 1; 引用类型: 名存在栈内存中,值存在于堆内存中,但是栈内存会提供一个引用的地址指向堆内存中的值; 浅...
  • 深拷贝浅拷贝

    千次阅读 2019-12-25 11:34:46
    深拷贝和浅拷贝的区别 1.浅拷贝: 将原对象或原数组的引用直接赋给新对象,新数组,新对象/数组只是原对象的一个引用 2.深拷贝: 创建一个新的对象和数组,将原对象的各项属性的“值”(数组的所有元素)拷贝过来,...
  • BeanUtils.copyProperties的使用(深拷贝,浅拷贝)

    万次阅读 多人点赞 2020-03-18 23:30:05
    这里说的是spring的BeanUtils.copyProperties。 场景 开发中经常遇到,把父类的属性拷贝到子类中。通常有2种方法: 1、一个一个set ...是深拷贝,还是浅拷贝? 是浅拷贝。 浅拷贝: 只是调用子对象的set...
  • 深拷贝与浅拷贝的区别 假如复制A得到了B,如果B中的某个属性发生改变,与此同时如果A中的值也发生改变,叫浅拷贝; 如果A中的值未发生任何变化,叫做深拷贝; 为什么会发生如此变化 主要是因为数据类型的原因 ...
  • Golang深拷贝浅拷贝

    万次阅读 2019-05-30 23:19:37
    Golang深拷贝浅拷贝 在了解原型设计模式之前我们需要新知道Golang的深拷贝与浅拷贝之间的区别。 推荐大家新看看Slice 和 Map那么常见的坑:https://blog.csdn.net/weixin_40165163/article/details/90707593 ...
  • 深拷贝与浅拷贝的区别,实现深拷贝的几种方法

    万次阅读 多人点赞 2018-08-28 11:09:49
    如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。 此篇文章中也会简单阐述到栈堆,基本...
  • 代码实现深拷贝   经过对浅拷贝的简单了解,咱们就到了如何实现深拷贝的问题上,常见的循环遍历,只是遍历了一层数据,明显解决不了这个问题,不过咱们可以看出,深拷贝的问题不就在于怎么解决无限层级拷贝问题吗...
  • javascript 数组以及对象的深拷贝(复制数组或复制对象)的方法 前言 在js中,数组和对象的复制如果使用=号来进行复制,那只是浅拷贝。如下图演示: 如上,arr的修改,会影响arr2的值,这显然在绝大多数情况下,并...
  • 深拷贝和浅拷贝说起深拷贝和浅拷贝,首先我们来看两个栗子// 栗子1var a = 1,b=a;console.log(a);console.log(b)b = 2;console.log(a);console.log(b)// 栗子2var obj1 = {x: 1, y: 2}, obj2 = obj1;console.log(obj...
  • 1. 首先使用JSON.parse来实现一个深拷贝 let test = { x : 1, y : 2, z : { a : 4, b : 5 } } // 深拷贝 let result = JSON.parse(JSON.stringify(test)); // 改变拷贝后的值 result.z.a = 40; console.log...
  • js拷贝对象 浅克隆深克隆 深拷贝浅拷贝 对象简介 js程序中都是用对象结构来描述显示中一个事物,对象就是一组属性和方法的集合。 面向对象三大特点: 封装,继承,多态。 克隆对象 浅克隆是克隆 一层,深层次的对象...
  • ECMAScript中的浅拷贝和深拷贝

    万次阅读 2020-02-07 19:09:27
    一.什么是浅拷贝,什么是深拷贝 浅拷贝:浅拷贝是将原始对象中...深拷贝:深拷贝深拷贝是在引用方面不同,深拷贝就是创建一个新的和原始字段的内容相同的字段,是两个一样大的数据段,所以两者的引用是不同的,之后...
  • 深拷贝 说到深拷贝,肯定想到的最简单的方式就 JSON.stringify 和 JSON.parse 配合,这个是最简单的深拷贝方式 手写一个深拷贝 深拷贝 = 浅拷贝 + 递归 ,这个只是最笨的一种方式 var a = { name: "muyiy", book: {...
  • * 深拷贝 */ //判断类型 function isType(arg) { var type = Object.prototype.toString.call(arg); type = (type.slice(8, type.length - 1)).toLowerCase(); return type; } //深拷贝对象 function deepFul.....
  • 所谓深拷贝就是将源对象克隆了一份保存在内存中,后续对复制的对象所有操作都不会影响源对象。 因为Map的putAll()的拷贝方式实现的是浅拷贝,所以后续对复制对象操作会影响到源对象。 在java中,对象的赋值都是对象...
  • 深拷贝 vs 浅拷贝 浅拷贝 概念 复制基本类型的属性;引用类型的属性复制,复制栈中的变量 和 变量指向堆内存中的对象的指针,不复制堆内存中的对象。 如图: ​ 特点 ​ 1.对于基本数据类型的成员对象,因为基础...
  • 如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。 此篇文章中也会简单阐述到栈堆,基本...
  • 深拷贝和浅拷贝区别是什么?

    万次阅读 多人点赞 2019-06-18 15:44:47
    深拷贝和浅拷贝区别是什么? 复制一个 Java 对象 浅拷贝:复制基本类型的属性;引用类型的属性复制,复制栈中的变量 和 变量指向堆内存中的对象的指针,不复制堆内存中的对象。 深拷贝:复制基本类型的属性;...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 30,991
精华内容 12,396
关键字:

深拷贝