一、浅拷贝
浅拷贝在现实中最常见的表现在赋值上面,例如
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>测试</title> </head> <body> <script type="text/javascript"> //第一个数组 var test=["1","2","3"]; //第二个数组 var test2=[]; test2=test; test2[1]="two"; console.log(test);//运行的结果是["1","two","3"] </script> </body> </html>
从上面的例子,我们修改test2数组的值,最后打印test数组,发现test也跟着改变了。
其实这个就是一个最浅的浅拷贝,相当于test2=test这个阶段是在将test数组中的存储地址索引赋值给test2数组,所以两个数组都是指向同一块存储地址中去。
除了这种方法可以实现浅拷贝,还有使用slice和concat进行浅拷贝
例如:我们测试一次slice这个方法(可从已有的数组中返回选定的元素为新数组)
<script type="text/javascript"> var arr=["demo1","demo2","demo3"]; var arr2=arr.slice(0); arr2[1]="test"; console.log(arr);//["demo1","demo2","demo3"] console.log(arr2);//["demo1","test","demo3"] </script>
从上面的例子我们可以看出,使用slice方法对数组进行了深度拷贝,
同理,concat的用法如下(用于连接两个或多个数组为新数组)
<script type="text/javascript"> var arr=["demo1","demo2","demo3"]; var arr2=arr.concat(); arr2[1]="test"; console.log(arr);//["demo1","demo2","demo3"] console.log(arr2);//["demo1","test","demo3"] </script>
为何这样已经算得上是深拷贝的东西,我又称之为浅拷贝呢?
对于Slice和concat这两个方法来说都是浅拷贝,只能深拷贝数组中的第一层
当数组内为对象时,则是浅拷贝
二、深拷贝
1.通过内置的js函数
function deepCopy(o){ return JSON.parse(JSON.stringify(o)); } var a = {a:1,b:2,c:3}; var b = deepCopy(a); b.a = 4; alert(a.a); //1 alert(b.a); //4,将b.a赋值为4,不会影响到a对象,a.a仍是1
这种方式很好理解,对一个Object对象而言,
先使用内置的JSON.stringify()函数,将其转化为字符串 "{"a":1,"b":2}"
此时生成的字符串已经和原对象没有任何联系了,再通过JSON.parse()函数,将生成的字符串转化为一个新的对象。 {a: 1, b: 2}
而在新对象上的操作与旧对象是完全独立的,不会相互影响。这种方法的优点就是简单易懂,使用js内置函数来实现,不需要太大的开销。
2.以通过自己的方法实现,就是遍历数组或对象,返回新数组或者对象。
var simpleCopy = function(o){ if (o instanceof Array) { var n = []; for (var i = 0; i < o.length; ++i) { n[i] = o[i]; } return n; } else if (o instanceof Object) { var n = {} for (var i in o) { n[i] = o[i]; } return n; } }
3.如何实现拷贝包含对象或者数组的这种情况呢?那么就通过递归拷贝来实现。
var deepCopy = function(o) { if (o instanceof Array) { var n = []; for (var i = 0; i < o.length; ++i) { n[i] = deepCopy(o[i]); } return n; } else if (o instanceof Object) { var n = {} for (var i in o) { n[i] = deepCopy(o[i]); } return n; } else { return o; } }