运行结果如下:
<!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>
最近有点懒,这样不好不好!