JavaScript深拷贝,浅拷贝

我们今天来简单了解一下JavaScript中的深拷贝和浅拷贝。在提到深拷贝和浅拷贝时不得不提的就是值类型和引用类型。

我们就先来了解一下值类型和引用类型吧!

一、值类型和引用类型

「1.值类型」

JavaScript的简单数据类型(number,string,boolean ,null,nudefined)又称为基本数据类型。

包装类型:又称为原始值包装类型

number---Number

var k = 10   //k是值类型(基本类型)number
console.log(k)//10
var a = new Number(10)//k是number类型的对象
console.log(a)//number:10

 

string------String

boolean-----Boolean

var t = true   //t是值类型(基本类型)boolean
console.log(t)//true
var t = new Boolean(true)//t是Boolean类型的对象
console.log(t)//boolean:true

 

「2.引用类型」

复杂的数据类型(对象)

特点:变量中保存的是对象的一个引用地址。

var obj = //obj存放的是下面对象在内存中的地址
    {
      name:'aa',
      sex:'男',
      tel:'123445',
      age:13
    }
var fp = obj//将obj中的地址赋给fp

 

1.一个对象只能被一个变量引用,若这个变量又被重新赋值,则该对象变成没有任何引用的对象,此时JS的垃圾回收机制会自动释放该对象所占的内存空间

2.在函数的参数传递过程中

  • 实参向形参传递的是值(值传递):形参变了不会影响实参
  • 实参向形参传递的是引用(引用传递):本质传递的是对象的地址,形参变了实参也会变

3.如果在函数的参数中修改对象的属性或方法,则在函数外面通过引用这个对象的变量访问时的结果也是修改后的

function change(obj){
  obj.name = '小红'//在函数内修改了对象的属性
}
var stu = {name:'小明',age:18}
change(stu)
console.log(stu.name)//输出结果:小红

  

「3.值类型和引用类型的区别」

1.值类型和引用类型在内存存储的区别

 

以上函数testf在调用时,

  • 定义局部变量 age,由于age是局部变量,所以在栈中申请内存空间,起名为age,又由于给age赋的值24是基本类型,所以,值直接存储在栈中。
  • 定义局部变量arr,由于arr是局部变量,所以在栈中申请空间,但是arr的内存中存储的是什么?由于给arr赋的值不是基本类型,而是引用类型(new出来的),所以,先在堆中申请空间存放数据 12,23,34,。再把堆区的地址赋给arr。

2.值类型和引用类型在赋值时的区别

  • 值类型

 

  • 引用类型

 

了解了值类型和引用类,接下来我们就一起来讨论一下深拷贝和浅拷贝。

二、深拷贝和浅拷贝

因为值类型赋值的时,赋值的时数据,所以不存在深拷贝和浅拷贝的问题。 

 「1.浅拷贝」

var ninja = {
    name : '旗木卡卡西',
    address : '火影村',
    swage : '2000',
    friends : new Array('宇智波带土', '野原琳', '迈特凯') //这是引用类型
}

var ninja2 = {};
for(let key in ninja){
ninja2[key] = ninja[key];	
}
ninja2.friends[0] ="火影";
console.log(ninja2);
console.log(ninja);

 在控制台中打印的结果(ninja和ninja2的friends[0]都变成了“火影”): 

 

内存:

1.原始的对象ninja:

var ninja = {
    name : '旗木卡卡西',
    address : '火影村',
    swage : '2000',
    friends : new Array('宇智波带土', '野原琳', '迈特凯') //这是引用类型
}

2.浅拷贝的代码

var ninja2 = {};
for(let key in ninja){
ninja2[key] = ninja[key];	
}

  「2.深拷贝(初级)」

var ninja = {
    name : '旗木卡卡西',
    address : '火影村',
    swage : '2000',
    friends : new Array('宇智波带土', '野原琳', '迈特凯') //这是引用类型
}

var ninja2 = {};
for(let key in ninja){
	if(typeof ninja[key]=='object'){
		ninja2[key]=[];//因为,我上面写的是数组,所以,暂时赋值一个空数组.
		for(let i in ninja[key]){
			ninja2[key][i] = ninja[key][i]
		}
	}else{
		ninja2[key] = ninja[key];
	}
}
ninja2.friends[0] ="火影";
console.log(ninja2);
console.log(ninja);

 在控制台中打印的结果(只有ninja2的friends[0]变成了“火影”)

 内存

1.原始的对象ninja:

var ninja = {
    name : '旗木卡卡西',
    address : '火影村',
    swage : '2000',
    friends : new Array('宇智波带土', '野原琳', '迈特凯') //这是引用类型
}

2.深拷贝代码

var ninja2 = {};
for(let key in ninja){
	if(typeof ninja[key]=='object'){
		ninja2[key]=[];//因为,我上面写的是数组,所以,暂时赋值一个空数组.
		for(let i in ninja[key]){
			ninja2[key][i] = ninja[key][i]
		}
	}else{
		ninja2[key] = ninja[key];
	}
}

 「3.深拷贝(终级)」

1.如果对象的属性都是对象(引用类型),属性的属性也是引用类型,即嵌套多层,我们可以使用递归的方式来进行深拷贝。

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'){//如:key是wife,引用类型,那就递归
			newObj[key] = copyObj(obj[key])
		}else{//基本类型,直接赋值
			newObj[key] = obj[key];
		}
	}
	return newObj;
}
 
let pNew = copyObj(p);
pNew.wife.name='Miraitowa';
pNew.wife.address.city = '西安';
console.log(pNew);
console.log(p);

 2.如果属性是数组等非键值对的对象,那我们可以给数组增加一个自我复制的函数。

 function copyself(arr){
	let arrNew = new Array();
	for(let i in arr){
		arrNew[i]  = arr[i]
	}
	return arrNew;
}
 
var ninja = {
    name : '旗木卡卡西',
    address : '火影村',
    swage : '2000',
    friends : new Array('宇智波带土', '野原琳', '迈特凯') //这是引用类型
}
 
function copyObj(obj){
	let newObj={};
	for(let key in obj){
		if(typeof obj[key] =='object'){
			newObj[key] = copyself(obj[key]);
		}else{//基本类型,直接赋值
			newObj[key] = obj[key];
		}
	}
	return newObj;
}
 
var ninjaNew = copyObj(ninja);
ninjaNew.friends[0] = "火影";
console.log(ninjaNew);
console.log(ninja);  

  「4.总结」

       简单来说,浅拷贝就是只对指针进行拷贝,拷贝后两个指针指向同一个内存空间,用任意一个保存指针的变量对对象进行修改,两个指针所指向的对象都会被修改。

      深拷贝不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。用其中一个保存指针的变量对对象进行修改,这个指针所指向的对象都会被修改,另一个指针所指的对象不会被修改。

参考文献:https://blog.csdn.net/jiang7701037/article/details/98738487

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值