朋友去面试遇到的面试题~我也不会顺路来学习一下
本篇文章参考了[link]https://www.cnblogs.com/echolun/p/7889848.html
和[link]https://www.cnblogs.com/wxcbg/p/8569180.html
什么是深拷贝?
想要搞清楚什么是深拷贝,就需要先搞清楚一个数据的存储是在堆内存还是栈内存。
在JS中,基本数据类型有number,string,boolean,null,undefined。已经ES6中的symbol。这些基本数据类型是存储在栈内存中的。复制这些数据类型会将值直接复制过去。修改复制后的值不会对原值产生影响。
而对于引用数据类型:数组和对象,栈内存保存的是一个地址,指向的是堆内存中的数据。所以复制这些数据类型复制的只是这个地址。如果对复制后的数据进行修改,也会对原值产生影响。
var a = 1;
var b = a;
b = 10;
console.log("a为:",a,"b为:",b)
var obj1 = {text:"原来的内容"}
var obj2 = obj1
obj2.text = "修改的内容"
console.log("obj1为:",obj1,"obj2为:",obj2)
控制台打印输出的结果如下:
所以如果我们想要修改obj2的值而不影响到obj1的值,则需要进行深拷贝。
JSON实现深拷贝
var obj = {
id:1,
name:"cjx",
age:18,
say:"我是cjx",
array:[1,2,3,4]
}
console.log(obj)
var obj1 = JSON.stringify(obj)
var clone = JSON.parse(obj1)
console.log(obj1)
console.log("clone出来的对象",clone)
clone.name = "wf"
clone.array[2]=2
console.log("修改后的clone对象",clone)
打印出来的结果为
我们可以看到,使用JSON拷贝出来的对象实现了深拷贝的要求,我们去修改其数据不会影响到原值。将其方法提取成一个函数可以写成:
function deepClone(obj){
let obj1 = JSON.stringfy(obj)
let cloneObj = JSON.parse(obj1)
return cloneObj
}
JS原生实现深拷贝
最初的想法是遍历一遍对象的性质,将其都复制一遍即可。然后试了一下发现这样只能拷贝一层,如果对象的属性还有对象,那还是不能实现深拷贝。这个时候就需要使用递归了。
*小知识:typeof arr输出的还是Object。所以想要判断一个数组的类型,可以使用下面的三种方法:
arr.constructor === Array
arr instanceof Array
Array.isArray(arr)
所以,我们可以写出如下深拷贝的函数
function deepClone(arr){
var obj=arr.constructor==Array?[]:{};
//第二种方法 var obj=arr instanceof Array?[]:{}
//第三种方法 var obj=Array.isArray(arr)?[]:{}
for(var item in arr){
if(typeof arr[item]==="object"){
obj[item]=deepClone(arr[item]);
}else{
obj[item]=arr[item];
}
}
return obj;
}