在写代码的过程中发现复制一个对象时,当改变对象新的对象时,原来的对象也发生了变化,原来对象中是按引用传递,它们都是保存在一个内存的同个位置,改变对象时,也改变了引用的地址。但我们往往需要拷贝的是一个新的对象,改变值同时也不改变原来的,这时就需要用到深度拷贝和浅度拷贝了。
浅度拷贝:复制一层对象的属性,并不包括对象里面的为引用类型的数据,当改变拷贝的对象里面的引用类型时,源对象也会改变。
深度拷贝:重新开辟一个内存空间,需要递归拷贝对象里的引用,直到子属性都为基本类型。两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。
js基本类型的分类
基础类型:undefined 、 null、number、string、boolean、symbol
引用类型:object对象类型(Object 、Array 、Function 、Data)
浅拷贝
浅拷贝在我看来就是对一 "层" 简单类型的拷贝,
对于在a对象里面的包含b对象的浅拷贝,拷贝为c对象后 ,c对象中b'对象和a对象中的b对象指向的事同一块内存地址,对于a对象以及c对象的'一层',
基本类型的拷贝,实际上指向的是不同的内存地址。
function simpleCopy(obj1) {
var obj2 = Array.isArray(obj1) ? [] : {};
for (let i in obj1) {
obj2[i] = obj1[i];
}
return obj2;
}
var obj1 = {
a: 1,
b: 2,
c: {
d: 3
}
}
var obj2 = simpleCopy(obj1);
obj2.a = 3;
obj2.c.d = 4;
alert(obj1.a); // 1
alert(obj2.a); // 3
alert(obj1.c.d); // 4
alert(obj2.c.d); // 4
可以看到浅拷贝中,基本类型的拷贝,实际上指向的是不同的内存地址
深拷贝
- JSON.stringify与JSON.parse
- Array的slice和concat方法 返回新数组
JSON对象的parse和stringify
JSON对象是ES5中引入的新的类型(支持的浏览器为IE8+),JSON对象parse方法可以将JSON字符串反序列化成JS对象,stringify方法可以将JS对象序列化成JSON字符串,借助这两个方法,也可以实现对象的深拷贝。
//例
var source = { name:"source", child:{ name:"child" } }
var target = JSON.parse(JSON.stringify(source));
target.name = "target"; //改变target的name属性
console.log(source.name); //source
console.log(target.name); //target
target.child.name = "target child"; //改变target的child
console.log(source.child.name); //child
console.log(target.child.name); //target child