1.浅拷贝
浅拷贝:shallow copy,简单说,就是拷贝A对象里面的数据,但是不拷贝A对象里面的子对象。
常用的浅拷贝方式: - for in 循环 - 展开语法 - Object.assign
1).使用for in 实现浅拷贝
let person = {
name: 'zhangsan',
age: 20,
gender: '女',
car:{
brand: 'BMW',
price : 200000,
color: 'red'
}
}
let p = {}
for(let key in person) {
//key是当前属性名, obj[k]是当前属性值
p[key] = person[key]
}
console.log(p)
p.gender = '男';
p.car.brand = 'BENZ';
console.log("-------p object-------")
console.log(p)
console.log("-------person object-------")
console.log(person)
运行结果:
{
name: 'zhangsan',
age: 20,
gender: '女',
car: { brand: 'BMW', price: 200000, color: 'red' }
}
-------p object-------
{
name: 'zhangsan',
age: 20,
gender: '男',
car: { brand: 'BENZ', price: 200000, color: 'red' }
}
-------person object-------
{
name: 'zhangsan',
age: 20,
gender: '女',
car: { brand: 'BENZ', price: 200000, color: 'red' }
}
2).使用展开语法实现浅拷贝
let person = {
name: 'zhangsan',
age: 20,
gender: '女',
car:{
brand: 'BMW',
price : 200000,
color: 'red'
}
}
//展开语法实现浅拷贝
let p = {
...person
}
console.log(p)
p.gender = '男'
p.car.brand = 'BENZ';
console.log("-------p object-------")
console.log(p)
console.log("-------person object-------")
console.log(person)
运行结果:
{
name: 'zhangsan',
age: 20,
gender: '女',
car: { brand: 'BMW', price: 200000, color: 'red' }
}
-------p object-------
{
name: 'zhangsan',
age: 20,
gender: '男',
car: { brand: 'BENZ', price: 200000, color: 'red' }
}
-------person object-------
{
name: 'zhangsan',
age: 20,
gender: '女',
car: { brand: 'BENZ', price: 200000, color: 'red' }
}
我们发现由于是浅拷贝,所以改变p对象里car的属性也同时修改了person对象的car属性,因为这两个对象的car引用指向了同一个汽车对象。
3).Object.assign
let person = {
name: 'zhangsan',
age: 20,
gender: '女',
car:{
brand: 'BMW',
price : 200000,
color: 'red'
}
}
let p ={};
Object.assign(p, person); //浅拷贝
console.log(p)
p.gender = '男'
p.car.brand = 'BENZ';
console.log("-------p object-------")
console.log(p)
console.log("-------person object-------")
console.log(person)
运行结果与上面两种完全相同。
2.深拷贝
深拷贝:deep copy,简单说就是不仅要拷贝A对象里面的数据,也要拷贝它里面的子对象。
常见的深拷贝实现方式:
- JSON.stringify
- 自定义递归算法
- lodash
1).JSON.stringify 由于基本数据类型默认都是深拷贝,我们可以使用JSON.stringify把对象转换为字符串,实现深拷贝。但是这种方式无法拷贝function和undefined类型的属性。
let person = {
name: 'zhangsan',
age: 20,
gender: '女',
car:{
brand: 'BMW',
price : 200000,
color: 'red'
},
eat:()=>{
console.log(this.name+"is eating now...");
},
assets: undefined
}
let jsonStr = JSON.stringify(person);
let p = JSON.parse(jsonStr)
console.log(p)
p.gender = '男'
p.car.brand = 'BENZ';
console.log("-------p object-------")
console.log(p)
console.log("-------person object-------")
console.log(person)
运行结果:
{
name: 'zhangsan',
age: 20,
gender: '女',
car: { brand: 'BMW', price: 200000, color: 'red' }
}
-------p object-------
{
name: 'zhangsan',
age: 20,
gender: '男',
car: { brand: 'BENZ', price: 200000, color: 'red' }
}
-------person object-------
{
name: 'zhangsan',
age: 20,
gender: '女',
car: { brand: 'BMW', price: 200000, color: 'red' },
eat: [Function: eat],
assets: undefined
}
2).自定义递归算法
//封装函数
function deepCopy(newObj,obj) {
for(let key in obj) {
//判断属性值属于哪种数据类型
//属性值 obj[key]
//1.判断这个值是否为数组(数组也属于特殊对象,也是引用类型数据)
if(obj[key] instanceof Array) {
newObj[key] = []
deepCopy(newObj[key],obj[key]) //运用递归,把原对象属性值给新对象
//判断这个值是否为对象
} else if(obj[key] instanceof Object) {
newObj[key] = {}
deepCopy(newObj[key],obj[key]) //运用递归,把原对象属性值给新对象
} else {
//若是普通数据类型
newObj[key] = obj[key]
}
}
}
let person = {
name: 'zhangsan',
age: 20,
gender: '女',
car:{
brand: 'BMW',
price : 200000,
color: 'red'
},
eat:()=>{
console.log(this.name+"is eating now...");
},
assets: undefined
}
let p = {};
deepCopy(p,person);
console.log(p)
p.gender = '男'
p.car.brand = 'BENZ';
console.log("-------p object-------")
console.log(p)
console.log("-------person object-------")
console.log(person)
运行结果:
{
name: 'zhangsan',
age: 20,
gender: '女',
car: { brand: 'BMW', price: 200000, color: 'red' },
eat: {},
assets: undefined
}
-------p object-------
{
name: 'zhangsan',
age: 20,
gender: '男',
car: { brand: 'BENZ', price: 200000, color: 'red' },
eat: {},
assets: undefined
}
-------person object-------
{
name: 'zhangsan',
age: 20,
gender: '女',
car: { brand: 'BMW', price: 200000, color: 'red' },
eat: [Function: eat],
assets: undefined
}
这种方式同样存在,无法拷贝function类型的属性。
3).lodash
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>lodash实现深拷贝</title>
<!--CDN引入lodash类-->
<script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/lodash.js/4.17.21/lodash.min.js"></script>
</head>
<body>
<script>
//使用lodash实现对象深拷贝。
let person = {
name: 'zhangsan',
age: 20,
gender: '女',
car:{
brand: 'BMW',
price : 200000,
color: 'red'
},
eat:()=>{
console.log(this.name+"is eating now...");
},
assets: undefined
}
//lodash实现深拷贝
let p = _.cloneDeep(person);
console.log(p);
p.gender = '男'
p.car.brand = 'BENZ';
console.log("-------p object-------")
console.log(p)
console.log("-------person object-------")
console.log(person)
</script>
</body>
</html>
运行结果:

小结: 1. 浅拷贝:shallow copy,简单说,就是拷贝A对象里面的数据,但是不拷贝A对象里面的子对象。引用类型默认都是浅拷贝。浅拷贝常见的实现方式有:for in 循环,展开语法和Object.assign等等。 2. 深拷贝:deep copy,简单说就是不仅要拷贝A对象里面的数据,也要拷贝它里面的子对象。基本类型默认都是深拷贝。深拷贝常见的实现方式有:JSON.stringify,自定义递归算法和lodash工具类。 3. 推荐使用lodash工具类来轻松实现对象的深拷贝。