深拷贝与浅拷贝的介绍
在写代码前先简短介绍下JS中浅拷贝与深拷贝的区别。
JavaScript中有两种类型的对象拷贝:浅拷贝(Shallow Copy)、深拷贝(Deep Copy):
深复制和浅复制最根本的区别在于是否是真正获取了一个对象的复制实体,而不是引用。
浅拷贝——只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做“浅拷贝(浅复制)”,也就是说,浅复制仅仅是指向被复制的内存地址,如果两者中任一对象被改变了,那么另一个对象也会相应改变。
深拷贝——在计算机中开辟了一块新的内存地址用于存放复制的对象。
由此引出的问题
深拷贝和浅拷贝在复制对象为number时并没有什么问题,但当我们直接复制数组时就会引起下列的问题:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>deep-copy</title>
</head>
<body>
<script type="text/javascript">
var arr = [1,2,3,4,5,6];
var copyarr=new Array;
copyarr = arr;
arr[0]= "heihei";
document.write("arr"+"="+arr);
document.write("<br>")
document.write("copyarr"+"="+copyarr);
</script>
</body>
</html>
下面是运行结果:
很多时候,我们拷贝一个数组得到一个拷贝数组,是想对拷贝数组或者原数组进行一些操作而不想引起另一个数组发生改变,但是由于JS中深浅拷贝的存在,我们直接将原数组赋值给拷贝数组,这种操作相当于是把一个指向该数组的指针赋值给了拷贝数组,得到的是一个新指针(虽然在JS中讲指针并不合适但是在此用指针十分形象),属于浅拷贝,达不到我们要的效果。
这里很直观的我们会想到,利用for循环遍历数组一个个给拷贝数组赋值,发现确实两者不会相互改变,但还是属于浅拷贝,为什么这么说呐,因为当数组为二维(数组中包含数组)或者更高维度时,我们又遇到了前面的问题,因为三维及以上数组在实际中并不实用,所以下面介绍的数组深拷贝代码并不考虑三维及以上(其实实现也很简单,利用函数的浅拷贝然后判断是否i位为数组再进行浅拷贝的递归功能即可)。
二维数组的深拷贝
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<script type="text/javascript">
// 定义一个名为newCopy的函数(函数名字可以随意改,使用函数时改成你改的名字即可)
function newCopy(arr) {
// 在函数内使用var声明一个拷贝数组用于拷贝
var copyArr = new Array;
for (i = 0; i < arr.length; i++) {
// 判断第i位是否为数组(二维)
if (typeof arr[i] == "object") {
// 若第i位是数组我们就将copyArr的第i位也置为数组(这里使用
var声明会出错,因为copyArr[i]并不是一个变量)并用for循环赋值
copyArr[i] = new Array();
for (j = 0; j < arr[i].length; j++) {
copyArr[i][j] = arr[i][j];
}
// 如果不是数组则直接赋值
} else {
copyArr[i] = arr[i];
}
}
// 返回我们的拷贝数组
return copyArr;
}
// 以下可以用来检测是否为二维数组深拷贝
// var arr=[[1,2,30],2,5,8,7]
// var copyArr=newCopy(arr);
// arr[0][2]="heihie";
// copyArr[0][1]="ha";
// document.write(arr);
// document.write("<br>");
// document.write(copyArr);
</script>
</body>
</html>
上面的代码已经封装好了,可以直接复制到JS里面就可以直接使用该函数插件达到二维数组的深拷贝效果。
我们可以将最下面的注释激活来验证可行性,得到的效果如下:
可以发现实现了二维数组的深拷贝,两者改变自己互不影响。希望能帮到大家!