前端JS:什么是深拷贝?什么是浅拷贝?

栏目: JavaScript · 发布时间: 5年前

内容简介:什么是堆内存&&什么是栈内存?将原对象/原数组的引用,直接赋给新对象/新数组,新对象/数组只是原对象的一个引用,是指,建一个新的对象和数组,将原对象的各项属性的“值”(数组的所有元素)拷贝过来,是“值”而不是“引用”
  • 值类型(基本数据类型):String,Number,Boolean,Null,Undefined,Symbol

  • 引用数据类型数据

  • Object,Array,Function

    重点声明:Undefined 和 Null的区别;

  • Undefined 表示变量不含有值;

  • null:可以通过将变量的值设置为null来清空变量;

    {
      	var person,
      		car="moto";
      	 console.log(person);//undefined;
      	 console.log(car); // moto;
      	   car=null;
      	 console.log(car); // null		
      }
    复制代码

堆stack 和 栈heap

什么是堆内存&&什么是栈内存?

  • stack:为自动分配的内存空间,它由系统自动释放;
  • heap:为动态分配的内存空间,它大小不一定,也不会自动释放;

值 && 引用

  • 值数据类型的 变量和值 都存放在栈内存中,在变量申明之后,会动态分配一块内存区域,基本数据类型之间的赋值:是直接把栈内存中存的值,传值给变量;(传值)
  • 引用类型的变量存在栈内存中,但是值存在堆内存中;实际上栈存放的是,指向堆中的地址,即“引用”。引用类型直接的赋值,实质上是把“引用”赋值给一个变量(传址),所以其指向的堆内存中的值是一样的;

深拷贝和浅拷贝

  • 使用场景:
    • 深拷贝:在复杂对象里,对象的属性也是对象的时候;
    • 浅拷贝:只复制一层对象,当对象的属性是引用类型时,实质上复制的是其引用,当引用指向的值发生变化的时候,原对象属性值也跟着变化;

浅拷贝

将原对象/原数组的引用,直接赋给新对象/新数组,新对象/数组只是原对象的一个引用, Just show the code :

举例1:
		let obj={a:1,arr:[2,3]};	

		let shallowObj=shallowCopy(obj);
		
		function shallowCopy(srcObj){
			var dest={};
			for(let prop in srcObj){
					console.log(prop);
				if(srcObj.hasOwnProperty(prop)){
					dest[prop]=srcObj[prop]
					

					}

				}// end of loop
				
				return dest;
			} 
		
// 1.举例: 当一个对象属性的引用值改变时,会导致另一个也改变;
	
	shallowObj.arr[1]=5;
	console.log(obj.arr[1]); // 5
	
// 2.举例:console:

	let obj2=obj;
		
		obj2
		{a: 1, arr: Array(2)}
		obj2.arr
		(2) [2, 3]
		obj2.arr[1]=4
		4
		obj2.arr
		(2) [2, 4]
		obj.arr
		(2) [2, 4]
复制代码

深拷贝:

是指,建一个新的对象和数组,将原对象的各项属性的“值”(数组的所有元素)拷贝过来,是“值”而不是“引用” 我们希望在改变新的数组(对象)的时候,不改变原数组(对象)

1.只对第一层级深拷贝

1.直接遍历:

var array = [1, 2, 3, 4];
function copy (array) {
   let newArray = []
   for(let item of array) {
      newArray.push(item);
   }
   return  newArray;
}
var copyArray = copy(array);
copyArray[0] = 100;
console.log(array); // [1, 2, 3, 4]
console.log(copyArray); // [100, 2, 3, 4]
复制代码

2.slice(); arrObj.slice(start,end);

slice() 方法返回一个从已有的数组中截取一部分元素片段组成的新数组

var array = [1, 2, 3, 4];
var copyArray = array.slice();
copyArray[0] = 100;
console.log(array); // [1, 2, 3, 4]
console.log(copyArray); // [100, 2, 3, 4]
复制代码

3.concat();arrObj.concat(arr1,arr2...);

var array = [1, 2, 3, 4];
var copyArray = array.concat();
copyArray[0] = 100;
console.log(array); // [1, 2, 3, 4]
复制代码

因为我们上面调用concat的时候没有带上参数,所以var copyArray = array.concat();实际上相当于var copyArray = array.concat([]);

也即把返回数组和一个空数组合并后返回

4.ES6的Object.assign();

Object.assign:用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target),并返回合并后的target Object.assign(target, source1, source2);

var obj = {
	  name: '彭湖湾',
	  job: '学生'
	}
	var copyObj = Object.assign({}, obj);
	copyObj.name = '我才不叫彭湖湾呢! 哼  (。・`ω´・)';
	console.log(obj);   // {name: "彭湖湾", job: "学生"}
	console.log(copyObj);  // {name: "我才不叫彭湖湾呢! 哼  (。・`ω´・)", job: "学生"}
复制代码

所以copyObj=Object.asssign({},obj);是将代码中obj的一级属性,拷贝到{}中,然后将其返回给copyObj;

5 ES6扩展运算符:

扩展运算符(...)用于取出参数对象的所有可遍历属性,拷贝到当前对象之中 var copyObj=[...arr] function copy(obj){ if(typeof obj !==="object"){ return ; }

let newObj= obj.constructor===Array?[]:{};

		if(newObj instanceof Array){
			 newObj=[...obj];
			return	newObj;
		}else if(newObj instanceof Object){
			newObj={...obj};	
			return newObj;
		} 

		}
复制代码

多次级深拷贝;

1.递归方式实现深拷贝

function deepCopy(obj){

		if(obj instanceof Array){
		let n=[];
		for(let i=0;i<obj.length;i++){
		
			n[i]=deepCopy(obj[i]);
			
			}// end of for
			return n;
		}// end of if ;
		if(obj instanceof Object){
		let n={};
			for(let i in obj){
		      n[i]=deepCopy(obj[i]);
			
			}// end of for
		 return n;	
		} else { //// end of if 
		
		 return obj;
	
		}
	}
复制代码

2.JSON.parse(JSON.stringify(strObj));

var arrObj=[
		{num:1},
		{num:2},
		{num:3}
	];
	var copyArray=JSON.parse(JSON.stringify(arrObj));
	
	copyArray[2].num=4;

    console.log(arrObj); // [{num:1},{num:2},{num:3}];
	console.log(copyArray); // [{num:1},{num:2{num:4}];
复制代码

3.递归2:

function copy(obj){
		let newObj=obj.constructor===Array?[]:{};
		if(type of obj !="object"){
			return;
		}
        for(let i in obj){
		newObj[i]= typeof obj[i]==="object"?copy(obj[i]):obj[i]
		
		}
		return newObj;
	}
复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Imperfect C++中文版

Imperfect C++中文版

威尔逊 / 荣耀、刘未鹏 / 人民邮电出版社 / 2006-1 / 75.0

汇集实用的C++编程解决方案,C++虽然是一门非凡的语言,但并不完美。Matthew Wilson使用C++十年有余,其间发现C++存在一些固有的限制,需要一些颇具技术性的工作进行弥补。本书不仅指出了C++的缺失,更为你编写健壮、灵活、高效、可维护的代码提供了实用的技术和工具。Wilson向你展示了如何克服C++的复杂性,穿越C++庞大的范式阵列。夺回对代码的控制权,从而获得更理想的结果。一起来看看 《Imperfect C++中文版》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具