zoukankan      html  css  js  c++  java
  • 几个例子理解浅拷贝和深拷贝

    一、内存的堆栈

    1. 基本类型
      存放在栈内存中的简单数据段,数据大小确定,内存空间大小可以分配,当它赋给另一个变量的时候,另一个变量发生改变,原数据不会发生改变:
      var a = 5;
      var b = a;
      b += 1;
      console.log(b)  //6
      console.log(a)  //5
    

    5种基本数据类型有Undefined、Null、Boolean、Number 和 String,它们是直接按值存放的,所以可以直接访问。

    1. 引用类型
      存放在堆内存中的对象,变量实际保存的是一个指针,这个指针指向另一个位置。每个空间大小不一样,要根据情况进行特定的分配。当我们需要访问引用类型(如对象,数组,函数等)的值时,首先从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据。
      var a = { userName : 'undefined' };
      var b = a;
      b.userName = 'xiaoming';
      console.log(a);  //{userName: "xiaoming"}
      console.log(b);  //{userName: "xiaoming"}
    

    上面的例子把a的值赋值给b,当b的值发生改变的时候,a的值也会跟随改变,像上面的图解一样,a和b都是指向同一个地址。如果要让b得到一个独立的地址呢?这就涉及到拷贝了。

    二、Object.assign

    浅拷贝是复制浅层的引用类型,比如复制a = { userName : 'undefined' }这样的对象就是属于浅拷贝,它只有一层,像复制b = { info : { userName : 'undefined' } }这样有嵌套的对象,多层的引用类型,就需要用到深拷贝了。

    • Object.assign()方法可以得到一份浅拷贝的引用类型
      var a = { userName : 'undefined' };
      var b = Object.assign({} , a);
      b.userName = 'xiaoming';
      console.log(a);  //{userName: "undefined"}
      console.log(b);  //{userName: "xiaoming"}
    

    这样,我们就能得到一份浅拷贝内容了,即使是b发生改变,也不会影响到a,它们完全是两个独立的个体,但是此方法不适用深拷贝。

    三、展开运算符

    • 利用展开运算符方法也可以得到一份浅拷贝的引用类型:
      var a = { userName : 'undefined' };
      var b = {...a};
      b.userName = 'xiaoming';
      console.log(a);  //{userName: "undefined"}
      console.log(b);  //{userName: "xiaoming"}
    

    这样,我们也能得到一份浅拷贝内容。

    四、JSON.parse()&JSON.stringify()

    • 利用JSON下面的parse()方法和stringify()方法可以得到一份深拷贝内容,stringify()方法可以把对象转变成json格式的字符串,再通过parse()方法进行转译成对象来获得一份拷贝的对象(当然浅拷贝也是适用的):
      var a = { info:{userName : 'undefined'}};
      var b = JSON.parse(JSON.stringify(a));
      b.info.userName = 'xiaoming';
      console.log(a);  // { info:{userName : 'undefined'}};
      console.log(b);  // { info:{userName : 'xiaoming'}};
    

    五、for...in&递归(推荐)

    • 这种方法适用于任何引用类型,原理是使用for..in循环,配合递归函数实现深层拷贝 :
    		var a = { info:{userName : 'undefined'}};
    		var b = copy(a);
    		b.info.userName = 'xiaoming'
    		function copy(obj){
    			var result = {};
    			for(var attr in obj){
    				if( typeof obj[attr] === 'object' ){
    					result[attr] = copy(obj[attr]);
    				}
    				else{
    					result[attr] = obj[attr];
    				}
    			}
    			return result;
    		}
    
    		console.log(a);   // { info:{userName : 'undefined'}};
    		console.log(b);   //{userName: "xiaoming"}
    

    这样,就可以得到一份深拷贝内容了,其原理就是层层拷贝,利用递归的原理,直到最底层不是对象为止,好啦,本次分享就到这里了,如果有什么不正确的地方,请各位不吝赐教,谢谢~

  • 相关阅读:
    P168 实战练习(权限修饰符)
    Java—面向对象—权限修饰符及思维导图
    P168 实战练习(构造方法)
    Java—面向对象—构造方法及相关思维导图
    面向对象编程(OOP)
    随堂练习——猜生日
    正则表达式
    P141 实战练习——字符串(修改后)
    java经典问题
    java开发环境
  • 原文地址:https://www.cnblogs.com/xwkj/p/10127819.html
Copyright © 2011-2022 走看看