数组拷贝
var arr = [{old: 'old'}, ['old']];
var new_arr = arr.concat();
arr[0].old = 'new';
new_arr[1][0] = 'new';
console.log(arr); // [{old: 'new'}, ['new']]
console.log(new_arr); // [{old: 'new'}, ['new']]
// 如果数组元素是基本类型,就会拷贝一份,互不影响,而如果是对象或者数组,就会只拷贝对象和数组的引用,这样我们无论在新旧数组进行了修改,两者都会发生变化。这种叫浅拷贝
// 深拷贝就是指完全的拷贝一个对象,即使嵌套了对象,两者也相互分离,修改一个对象的属性,也不会影响另一个。
for实现数组的深拷贝
var arr = [1,2,3,4,5]
var arr2 = copyArr(arr)
function copyArr(arr) {
let res = []
for (let i = 0; i < arr.length; i++) {
res.push(arr[i])
}
return res
}
slice 方法实现数组的浅拷贝
他是将原数组中抽离部分出来形成一个新数组
var arr = [1,2,3,4,5]
var arr2 = arr.slice(0)
arr[2] = 5
concat 方法实现数组的浅拷贝
var arr = [1,2,3,4,5]
var arr2 = arr.concat()
arr[2] = 5
ES6扩展运算符实现数组的深拷贝
var arr = [1,2,3,4,5]
var [ ...arr2 ] = arr
arr[2] = 5
浅拷贝和深拷贝都是对于JS中的引用类型而言的,浅拷贝就只是复制对象的引用(堆和栈的关系,简单类型Undefined,Null,Boolean,Number和String是存入堆,直接引用,object array 则是存入桟中,只用一个指针来引用值),如果拷贝后的对象发生变化,原对象也会发生变化。只有深拷贝才是真正地对对象的拷贝。
对象浅拷贝
var object1 = {
a: 1,
obj: {
b: 'string'
}
};
// 浅拷贝
var copy = Object.assign({}, object1);
// 改变原对象属性
object1.a = 2;
object1.obj.b = 'newString';
console.log(copy.a); // 1
对象深拷贝
var obj = { a: 1, b: { c: 2 }};
// 深拷贝
var newObj = JSON.parse(JSON.stringify(obj));
// 改变原对象的属性
obj.b.c = 20;
console.log(obj); // { a: 1, b: { c: 20 } }
console.log(newObj); // { a: 1, b: { c: 2 } }
对象必须遵从JSON的格式
扩展运算符实现对象的深拷贝
var obj = {
name: 'FungLeo',
sex: 'man',
old: '18'
}
var { ...obj2 } = obj
obj.old = '22'
console.log(obj)
console.log(obj2)
数组对象深拷贝
let arr = [1, {a: 2}];
function deepCopy(arr) {
let copyArr = (arr.constructor === Array) ? [] : {}; // 判断是数组还是对象
for(let i in arr) {
if(typeof arr[i] === 'object') { // 判断是值类型还是引用类型
copyArr[i] = deepCopy(arr[i]); // 引用类型的话进行递归操作
} else {
copyArr[i] = arr[i]; // 值类型直接赋值
}
}
return copyArr;
}
let copyArr = deepCopy(arr);
console.log(copyArr ) // [1, {a: 2}]
arr[1].a = 3;
console.log(copyArr ) // [1, {a: 2}]
copyArr[1].a = 5;
console.log(arr) // [1, {a: 2}]