引言
浅拷贝:copy对象值的改变会引起原对象值的改变
深拷贝:copy对象值的改变不会引起原对象值的改变
浅拷贝
- 方法一 ( = 赋值)
let test = {
name: 'test',
};
let demo = test;
demo.name = 'demo';
console.log(test); // { name: 'demo' }
console.log(demo == test);
- 方法二 (Object.assign) 二级属性
//注意:copy类型必须有二级属性,且浅拷贝的是二级属性对象
let test = {
name: 'test',
arr: [1, 2],
};
let demo = Object.assign({}, test);
demo.name = 'demo';
demo.arr[0] = 3;
console.log(test); //{ name: 'test', arr: [ 3, 2 ] }
console.log(demo);// { name: 'demo', arr: [ 3, 2 ] }
console.log(demo.arr == test.arr); // true
- 方法三(…展开运算符 ) 二级属性
//表现与Object.assign一样
let test = {
name: 'test',
arr: [1, 2],
};
let demo = {...test};
demo.name = 'demo';
demo.arr[0] = 3;
console.log(test); //{ name: 'test', arr: [ 3, 2 ] }
console.log(demo);// { name: 'demo', arr: [ 3, 2 ] }
console.log(demo.arr == test.arr); // true
深拷贝
1.方法一 (JSON.parse.stringify)
//注意:无法拷贝一些特殊属性如:undefined,Date,RegExp,循环引用
let test = {
name: 'test',
arr: [1, 2],
};
let demo = JSON.parse(JSON.stringify(test));
demo.name = 'demo';
demo.arr[0] = 3;
console.log(test); //{ name: 'test', arr: [ 1, 2 ] }
console.log(demo);// { name: 'demo', arr: [ 3, 2 ] }
console.log(demo.arr == test.arr); // false
2.方法二 (JQuery.extend)
//用法跟Object.assign差不多
//第一个参数为true时为深拷贝,默认false为浅拷贝
let test = {
name: 'test',
arr: [1, 2]
};
let demo = $.extend(true, {}, test);
demo.name = 'demo';
demo.arr[0] = 3;
console.log(test); //{ name: 'test', arr: [ 1, 2 ] }
console.log(demo);// { name: 'demo', arr: [ 3, 2 ] }
console.log(demo.arr == test.arr); // false
- 方法三(lodash.cloneDeep)
//loadash函数库
let test = {
name: 'test',
arr: [1, 2]
};
let demo = _.cloneDeep(test);
demo.name = 'demo';
demo.arr[0] = 3;
console.log(test); //{ name: 'test', arr: [ 1, 2 ] }
console.log(demo);// { name: 'demo', arr: [ 3, 2 ] }
console.log(demo.arr == test.arr); // false
- 方法四 (手写)
let test = {
name: 'test',
arr: [1, 2]
};
let demo = deepCopy(test);
demo.name = 'demo';
demo.arr[0] = 3;
console.log(test); //{ name: 'test', arr: [ 1, 2 ] }
console.log(demo);// { name: 'demo', arr: [ 3, 2 ] }
console.log(demo.arr == test.arr); // false
// map 解决循环引用
function deepCopy(source, map = new Map()) {
if (source instanceof Date) return source;
if (source instanceof RegExp) return source;
if (typeof source === 'object') {
let target = Array.isArray(source) ? [] : {};
if (map.get(source)) {
return map.get(source);
}
map.set(source, source);
for (const key in source) {
target[key] = deepCopy(source[key], map);
}
return target;
} else {
return source;
}
}
特殊数据(供深拷贝测试)
let test = {
a: 1,
b: {
b1: 2,
b2: 3
},
c: ['1', '2', '3'],
d: undefined,
e: new Date(),
f: /[a-zA-Z]/g,
}
//循环引用
test.a = test;
其他
深拷贝(一级属性)
// Object.assign()
// ...展开运算符
//Array.slice
//Array.concat
//Array.map
//总之数组方法能够返回新数组的都可以
let test = {
a: 'test',
b: 0,
c: false,
}
// let demo = Object.assign({}, test);
let demo = { ...test };
demo.a = 'demo';
demo.b = 1;
demo.c = true;
console.log(test); //{ a: 'test', b: 0, c: false }
console.log(demo); //{ a: 'demo', b: 1, c: true }
let arr = [0, 1, 2, 3];
let num = arr.slice(0);
//let num = arr.concat();
//let num = arr.map( item => item );
num[0] = 3;
console.log(arr); //[ 0, 1, 2, 3 ]
console.log(num); //[ 3, 1, 2, 3 ]