深拷贝:开辟一个新的内存地址,浅拷贝指针指向同一片内存空间
浅复制只复制一层对象的属性,而深复制则递归复制了所有层级
浅拷贝(合并)的实现
1.遍历赋值
var obj = { a:1, arr: [2,3] };
var shallowObj = shallowCopy(obj);
function shallowCopy(src) {
if(typeof src !== 'object') return
var dst= Array.isArray(src) ? [] : {}
for ( var prop in src) {
if (src.hasOwnProperty(prop) { //此处hasOwnProperty是判断自有属性,使用 for in 循环遍历对象的属性时,原型链上的所有属性都将被访问会避免原型对象扩展带来的干扰
dst[prop] = src[prop]
}
}
return dst
}
2.Object.assign() 可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。【// 如果数组元素是基本类型,就会拷贝一份,互不影响,而如果是对象或者数组,就会只拷贝对象和数组的引用,这样我们无论在新旧数组进行了修改,两者都会发生变化。这种叫浅拷贝】
var x = {
a: 1,
b: { f: { g: 1 } },
c: [ 1, 2, 3 ]
};
var y = Object.assign({}, x);
console.log(y.b.f === x.b.f); // true
合并对象 Object.assign()
如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖。后面的源对象的属性将类似地覆盖前面的源对象的属性。
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };const returnedTarget = Object.assign(target, source);
console.log(target);
// expected output: Object { a: 1, b: 4, c: 5 }
3.$.extend()
var obj1={'a':1}; var obj2={'b':{'b1':22,'b2':33}}; $.extend(obj1, obj2); //obj1拷贝了obj2的属性 console.log(obj1) // {'a':1,'b'{'b1':22,'b2':33}} console.log(obj1.b.b1) // 22 obj2.b.b1=44; //obj2重新赋值 console.log(obj1.b.b1) // 44 obj1.b仅拷贝了对象的指引,所以受原obj2的影响
深拷贝的实现
var obj1={'a':1}; var obj2={'b':{'b1':22,'b2':33}}; $.extend(true,obj1, obj2); //第一个参数设为true表示深复制 console.log(obj1) // {'a':1,'b'{'b1':22,'b2':33}} console.log(obj1.b.b1) // 22 obj2.b.b1=44; //obj2重新赋值 console.log(obj1.b.b1)
数组的合并
concat
方法用于多个数组的合并。它将新数组的成员,添加到原数组成员的后部,然后返回一个新数组,原数组不变。 // 如果数组元素是基本类型,就会拷贝一份,互不影响,而如果是对象或者数组,就会只拷贝对象和数组的引用,这样我们无论在新旧数组进行了修改,两者都会发生变化。这种叫浅拷贝
const a = [1, 2, 3]
const b = [4, 5, 6]
const c = a.concat(b)
c[0] = 9
console.log(c) // [ 9, 2, 3, 4, 5, 6 ]
console.log(a) //[1,2,3] //数组不是引用型则为深拷贝
如果数组成员包括对象,concat方法返回当前数组的一个浅拷贝。所谓“浅拷贝”,指的是新数组拷贝的是对象的引用。
var obj = { a: 1 };
var oldArray = [obj];var newArray = oldArray.concat();
obj.a = 2;
newArray[0].a // 2
slice方法 // 如果数组元素是基本类型,就会拷贝一份,互不影响,而如果是对象或者数组,就会只拷贝对象和数组的引用,这样我们无论在新旧数组进行了修改,两者都会发生变化。这种叫浅拷贝
slice 方法实现数组的拷贝
slice() 方法可从已有的数组中返回选定的元素。
arrayObject.slice(start,end)
该方法返回一个新的数组,包含从 start 到 end (不包括该元素,数学上来讲是左闭右开,即包含左,不含右)的 arrayObject 中的元素。
1 var arr1 = [1, 2, 3];
2 var arr2 = arr1.slice(0);
3 arr1[0] = 4;
4 console.log(arr1); //4, 2, 3
5 console.log(arr2); //1, 2, 3
for循环
var a = [ ] for (var i in b) { a.push(b[i]) }
- …扩展运算符
-
const a1 = [1, 2]; // 写法一 const a2 = [...a1]; // 写法二 const [...a2] = a1; // ES6 的合并数组 [...arr1, ...arr2, ...arr3]
递归实现深拷贝
function deepClone(obj) {
if (typeof obj !== 'object') return;
let objClone = Array.isArray(obj) ? []:{}
for (key in obj) {
if(obj.hasOwnObjectProperty(key)) {
objClone[key] = typeof obj[key] === "object" ? deepClone(obj[key]) : obj[key]
}
}
JSON对象的parse和stringify实现深拷贝
function deepClone(obj){
let _obj = JSON.stringify(obj),
objClone = JSON.parse(_obj);
return objClone
}