首先,浅拷贝和深拷贝都是只针对于像Object,Array这样的复杂对象。
区别:浅拷贝只复制对象的第一层属性、深拷贝可以对对象的属性进行递归复制
一、手写一个浅拷贝方法和深拷贝方法
//浅拷贝
function shallowClone(target) {
let cloneTarget = {};
for (const key in target) {
cloneTarget[key] = target[key];
}
return cloneTarget;
}
//深拷贝
function deepClone(target) {
if (typeof target === 'object') { // 是对象的话要进行深拷贝
let cloneTarget = {};
for (const key in target) {
cloneTarget[key] = deepClone(target[key]); //递归
}
return cloneTarget;
} else { //普通值/函数不需要深拷贝
return target;
}
}
二、浅拷贝的实现方法[obj为普通对象,copyObj为复制后的新对象]
1)Object.assign()对象合并
let copyObj = Obiect.assign({},obj)
//花括号里叫目标对象,obj为源对象
📢 Object.assign()方法属于es6中新增的对象的扩展
2)函数库lodash的_.clone方法
var _ = require('lodash');
var obj1 = {
a: 1,
b: { f: { g: 1 } },
c: [1, 2, 3]
};
var obj2 = _.clone(obj1);
console.log(obj1.b.f === obj2.b.f);// true
3)展开运算符
- 通过展开运算符 ... 来实现浅拷贝
- 展开运算符是一个 es6 / es2015特性,它提供了一种非常方便的方式来执行浅拷贝,这与Object.assign ()的功能相同。
- 如果只是一层数组或对象,其元素只是简单类型的元素,那么这一层就不是浅拷贝!!(就是一层拷贝,你可以理解为深拷贝,但并不是深拷贝)
- 如果数组或对象中的元素是引用类型的元素,那么就是浅拷贝
let obj = { name: 'youzi', address:{x:100,y:100}}
let copyObj= {... obj1}
obj.address.x = 200;
obj.name = 'heyunchen' //此时copyObj的属性仍然是youzi,因为这一层不是引用类型的拷贝
console.log('copyObj',copyObj) //copyObj { name: 'youzi', address: { x: 200, y: 100 } }
4)Array.prototype.concat()或者 Array.prototype.slice()
- Array.concat(arr1,arr2…),合并两个或多个数组,生成一个新的数组。原数组不变。
- Array.slice() 按照条件查找出其中的部分内容
- 利用数组API,这两个都返回新数组,当数组中嵌套数组对象时为浅拷贝
- 数组对象:数组中含对象
let arr = [1, 3, {
username: 'kobe'
}];
let arr2 = arr.concat();
//let arr3 = arr.slice();
arr2[2].username = 'wade';
//arr3[2].username = 'wade';
console.log(arr); //[ 1, 3, { username: 'wade' } ]
三、深拷贝的实现
1)JSON.parse(JSON.stringify())
这是利用JSON.stringify将对象转成JSON字符串,再用JSON.parse把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝。
let a = {
age: 1,
jobs: {
first: 'FE'
}
}
let b = JSON.parse(JSON.stringify(a))
a.jobs.first = 'native'
console.log(b.jobs.first) // FE
2)函数库lodash的_.cloneDeep方法
var _ = require('lodash');
var obj1 = {
a: 1,
b: { f: { g: 1 } },
c: [1, 2, 3]
};
var obj2 = _.cloneDeep(obj1);
console.log(obj1.b.f === obj2.b.f);// false
3)jQuery.extend()方法
$.extend(deepCopy,target,obj1,[objN]) // 第一个参数为true就是深拷贝