javaScript中浅拷贝和深拷贝的区别

JavaScript深拷贝和浅拷贝

ES6函数

运行结果如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>javaScript中浅拷贝和深拷贝的区别</title>
<style type="text/css">
input[type=button] {
	background-color: #8E388E;
	border: 0px solid #8E388E;
	color: #fff;
	width: 160px;
	height: 40px;
	border-radius: 6px; /*把边框做成圆角*/
}

</style>
<script type="text/javascript">
// "use strict";//严格模式
/*
基本数据类型的值保存在内存中的栈中,
而引用数据类型的值保存在内存中的堆中,在栈内存中保存着指向堆内存的指针(引用)。
对于基本数据类型的值的复制,是对栈内存中的值直接进行复制,
所以复制的就是值本身,相当于复制了一个副本,会在栈中开辟一块全新的内存,
所以修改一个变量的值不会影响另外一个变量的值,
所以对于基本数据类型而言,没有浅拷贝和深拷贝之分,或者说直接就是深拷贝。
*/
window.onload = function() {
	var divNode = document.getElementById("div1");
	
	var role = {
			name : "韦小宝",
			age : 17
		};
	//role2和role指向的是相同的堆内存数据
		var role2 = role;
		
	divNode.innerHTML += role.name + "," + role.age + "<br />";
	console.log(role);
	divNode.innerHTML += role2.name + "," + role2.age + "<br />";
	console.log(role2, role2 == role);
	
	//无论是通过role2修改数据还是通过role修改数据,本质其实是修改的是同一块堆内存
	//所以,无论修改role2还是role,都会导致同一块堆内存中的数据发生改变
	role2.name = "令狐冲";
	role.age = 22;
	
	//如下结果可以看出,同一块堆内存中的数据发生了改变
	divNode.innerHTML += role.name + "," + role.age + "<br />";
	console.log(role);
	divNode.innerHTML += role2.name + "," + role2.age + "<br />";
	console.log(role2, role2 == role);
	
	//如何让role2和role中的数据不同,改变一个不会影响另外一个呢?先谈一下浅拷贝的解决办法。
	//浅拷贝可以使用Object.assign()来实现
	var person = {
			name : "张无忌",
			hometown : "江西省赣州市于都县"
		};
		divNode.innerHTML += person.name + "," + person.hometown + "<br />";
		var person2 = Object.assign({}, person);
		console.log((person2 == person) + "******");

		divNode.innerHTML += person2.name + "," + person2.hometown + "<br />";
		divNode.innerHTML += person.name + "," + person.hometown + "<br />";
		divNode.innerHTML += "************" + "<br />";
		person2.name = "周芷若";
		divNode.innerHTML += person2.name + "," + person2.hometown + "<br />";
		divNode.innerHTML += person.name + "," + person.hometown + "<br />";
		console.log((person2 == person) + "******");
	
		//如下是浅拷贝案例
/*
浅拷贝:
只拷贝了最浅层的对象,当对象里面嵌套的对象发生改变时,其内部值也会发生改变,
没有达到完全隔离的效果,只实现了浅层的拷贝。
*/
		
	var house = {
			id : 366,
			address : "江西省赣州市于都县渡江大道366号",
			desk : {
				brand : "全友家居",
				price : 2999
			}
		};
	divNode.innerHTML += house.id + "," + house.desk.price + "<br />";
	var house2 = Object.assign({}, house);
	
	divNode.innerHTML += house2.id + "," + house2.desk.price + "<br />";
	divNode.innerHTML += house.id + "," + house.desk.price + "<br />";
	divNode.innerHTML += "************" + "<br />";
	house2.desk.price = 3650;
	divNode.innerHTML += house2.id + "," + house2.desk.price + "<br />";
	divNode.innerHTML += house.id + "," + house.desk.price + "<br />";
	console.log("******" + (house2 == house));
	
	//如下是深拷贝案例
/*
实现深层拷贝方式有两种,
一种是通过JSON的方式,
JSON有两个方法JSON.parse()和JSON.stringify(),
前者可以将JSON字符串转换成JavaScript对象,
后者可以将JavaScript对象转换成JSON字符串。
所以解决思路就是先将引用类型数据变成JSON,再将其从JSON变回来,这样经过这样一层转换,
就会要求计算机从内存中重新开辟一块新的内存空间。book和book2之间就不会发生任何联系了。

另外一种是通过类型判断和递归的方式。 
*/	
	var book = {
			isbn : 8866,
			name : "西游记",
			price : 53.8,
			author : {
				name : "吴承恩",
				age : 23
			}
		};
	divNode.innerHTML += book.isbn + "," + book.author.age + "<br />";
	//通过JSON的方式
	var bookStr = JSON.stringify(book);
	console.log(bookStr, book);
	var book2 = JSON.parse(bookStr);
	//book == book2的结果为false,book === book2的结果为false
	console.log(book2, book, book == book2, book === book2);
	book2.author.age = 27;
	divNode.innerHTML += book2.isbn + "," + book2.author.age + "<br />";
	//book.author.age的值还是23,并没有发生改变(实现了深拷贝)
	divNode.innerHTML += book.isbn + "," + book.author.age + "<br />";
	
	//通过类型判断和递归的方式
	
	//判断数据的类型
	function checkType(data) {
		var dataType = Object.prototype.toString.call(data);
// 		console.log("======", dataType, dataType.slice(8, -1));
		return Object.prototype.toString.call(data).slice(8, -1);
	}
	
	var result1 = checkType({});
	var result2 = checkType([]);
	console.log(result1, result2);
	
	
	//通过递归的方式,实现深拷贝
	function deepClone(target) {
		var targetType = checkType(target);
		var result;
		// 初始化操作
		if (targetType === 'Object') {
			result = {};
		} else if (targetType === 'Array') {
			result = [];
		} else {
			// 都不是的话证明是基本数据类型,基本数据
			// 类型只会有一个值,所以直接返回这个值就可以了
			return target;
		}
		// target不是基本类型,进入遍历
		for ( var i in target) {
			var value = target[i];
			var valueType = checkType(value);
			if (valueType === 'Object' || valueType === 'Array') {
				result[i] = deepClone(value); // 递归
			} else {
				// 是基本类型直接赋值
				result[i] = value;
			}
		}
		return result;
	}
	
	
	var supermarket = {
			name : "沃尔玛超市",
			address : "纽约",
			dog : {
				name : "旺财",
				age : 3
			}
		};
	console.log(supermarket);
	var supermarket2 = deepClone(supermarket);
	console.log(supermarket2, supermarket);
	
	supermarket2.address = "华盛顿";
	supermarket2.dog.name = "小强";
	console.log(supermarket2);
	console.log(supermarket);
	
	
	var home = {
			name : "囧囧之家",
			address : "江西省赣州市于都县渡江大道6666号",
			fruits : ["苹果", "香蕉", "西瓜", "橘子", "雪梨"]
		};
	console.log(home);
	var home2 = deepClone(home);
	console.log(home2, home);
	
	home2.address = "于都县";
	home2.fruits[0] = "赣南脐橙";
	console.log(home2);
	console.log(home);
}


function fn1() {
	var testStr = "[object Object]";
	//slice(startIndex, endIndex)注意:不包括endIndex
	//-1表示最后一个字符的下标位置,-2表示倒数第二个字符的下标位置,-3,-4等等,以此类推
	console.log(testStr, testStr.slice(8, -1));
	//赣州市于都县渡江大
	console.log(testStr, "江西省赣州市于都县渡江大道".slice(3, -1));
}
</script>
</head>
<body style="background-color: #CCE8CF;">
<h1>javaScript中浅拷贝和深拷贝的区别</h1>
<input type="button" value="字符串的slice()函数" onclick="fn1();">
<div id="div1" style="background-color: Wheat; height: 100%;">
</div>
</body>
</html>

最近有点懒,这样不好不好!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值