深拷贝与浅拷贝的区别
1.浅拷贝
浅拷贝将原对象或原数组的引用直接赋给新对象,新数组,新对象/数组只是原对象的一个引用(拷贝后的引用都是指向同一个对象的实例,彼此之间的操作会互相影响)
2.深拷贝
深拷贝是将原对象的各个属性的“值”逐个复制出去,而且将原对象各个属性所包含的对象也依次采用深拷贝的方法递归复制到新对象上(注意拷贝的“值”而不是“引用”)
3.什么时候使用深拷贝
我们在希望改变新的数组(对象)的时候,不改变原数组(对象)
4.使用深拷贝的注意事项
如果对象比较大,层级也比较多,深拷贝会带来性能上的问题。所以在遇到需要使用深拷贝,考虑有没有其他的方案,实际应用中主要还是以浅拷贝为主
5.浅拷贝的实现方式
方式一 自定义函数
var obj = { a:1, arr: [2,3] };
var shallowObj = shallowCopy(obj);
obj.arr[0] = 10
console.log(shallowObj.arr[0]) // 10
function shallowCopy(src) {
var dst = {};
for (var prop in src) {
if (src.hasOwnProperty(prop)) {
dst[prop] = src[prop];
}
}
return dst;
}
方式二 ES6 Object.assign() // 多层是浅拷贝 一层是深拷贝
var obj = { a:1, arr: [1,2] };
let newObj = Object.assign({}, obj);
obj.arr[0] = 10
console.log(newObj.arr[0]) // 10
方式三 ES6 扩展运算符
var obj = { a:1, arr: [1,2] };
let newObj = {...obj};
obj.arr[0] = 10;
console.log(newObj.arr[0]); // 10
方式四 jQuery.extend()
var obj = { a:1, arr: [1,2] };
let newObj = jQuery.extend({}, obj);;
obj.arr[0] = 10;
console.log(newObj.arr[0]); // 10
方式五 数组方法(只适用于类数组对象) Array.from()
var array1 = ['a', ['b', 'c'], 'd'];
var array2 = Array.from(array1);
array1[1][0] = 'e';
console.log(array2[1][0]);//输出结果为: "e"
Array.concat()
Array.slice()
上面数组方法也可以实现浅拷贝,在这就不一一举例了
7.深拷贝的实现方式
方法一 用 JSON.stringify 把对象转换成字符串,再用 JSON.parse 把字符串转换成新的对象。可以转成 JSON 格式的对象才能使用这种方法,如果对象中包含 function 就不能用这种方法了。
var obj = { a:1, arr: [1,2] };
var newObj = JSON.parse(JSON.stringify(obj));
obj.arr[0] = 10;
console.log(newObj.arr[0]); // 1
方式二 jQuery.extend()
var obj = { a:1, arr: [1,2] };
var newObj = jQuery.extend(true, {}, obj);
obj.arr[0] = 10;
console.log(newObj.arr[0]); // 1
方式三 函数递归调用
var deepCopy = function(obj) {
if (typeof obj !== 'object') return;
var newObj = obj instanceof Array ? [] : {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
}
}
return newObj;
}
var obj = { a:1, arr: [1,2] };
var newObj = deepCopy(obj);
obj.arr[0] = 10;
console.log(newObj.arr[0]); // 1
方式四 Object.assign()
var obj = { a: 1 };
var newObj = Object.assign({}, obj);
obj.a = 10;
console.log(newObj.a); // 1