文章类型:个人学习笔记
前言
友情提醒:个人学习笔记,可能有写的不对的地方,还请大佬们发现了提醒一下小弟我。
1.浅拷贝
定义:一个对象直接拷贝已存在对象的属性的引用。
还没开始讲这篇文章的时候,让你自己去写一个拷贝,你会怎么写?
(1)直接赋值
1
2
3
4
5
6
7
|
let obj = {
name: '小明',
age: 20,
job: 'Software Engineer'
}
let obj1 = obj;
console.log(obj1 === obj); // true
|
(2)借助 ES6 的 Object.assign() 方法实现一个浅拷贝
1
2
3
4
5
6
7
8
9
10
|
let obj = {
name: '小明',
age: 20,
job: 'Software Engineer'
}
let obj1 = Object.assign({}, obj);
console.log(obj1 === obj); // false
obj1.age = 10;
console.log(obj.age); // 20
console.log(obj1.age); // 10
|
我们会发现,当对象内部属性全部为基础类型时,改变新拷贝的对象属性值,并不会影响到原对象,换句话说,如果你的对象里都是基础类型,你想对他进行拷贝,使用浅拷贝即可。
1
2
3
4
5
6
7
8
9
10
11
|
let obj = {
name: '小明',
age: 20,
job: 'Software Engineer',
friends: ['小花', '小丽']
}
let obj1 = Object.assign({}, obj);
console.log(obj1 === obj); // false
obj1.friends[1] = '小萌';
console.log(obj.friends); // ["小花", "小萌"]
console.log(obj1.friends); // ["小花", "小萌"]
|
当原对象中有属性时引用类型时,我们会发现改变新拷贝的引用类型属性值时,原对象的引用类型属性值也发生了改变,这就是拷贝的不够彻底,所以我们就需要深拷贝。
(3)借助 ES6 的展开语法实现浅拷贝
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
let obj = {
name: '小明',
age: 20,
job: 'Software Engineer',
friends: ['小花', '小丽']
}
let obj1 = { ...obj };
console.log(obj1 === obj);
obj1.age = 10;
obj.friends[0] = '小美';
console.log(obj.age); // 20
console.log(obj1.age); // 10
console.log(obj.friends); // ["小美", "小丽"]
console.log(obj1.friends); // ["小美", "小丽"]
|
(4)遍历赋值的方法实现浅拷贝
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
let obj = {
name: '小明',
age: 20,
job: 'Software Engineer',
friends: ['小花', '小丽']
}
let obj1 = {};
for (const item of Object.entries(obj)) {
obj1[item[0]] = item[1];
}
console.log(obj1 === obj);
obj1.age = 10;
obj.friends[0] = '小美';
console.log(obj.age); // 20
console.log(obj1.age); // 10
console.log(obj.friends); // ["小美", "小丽"]
console.log(obj1.friends); // ["小美", "小丽"]
|
2.深拷贝
复制一个一模一样的对象,不共享内存,修改一个对象,不会影响到另一个对象
(1)利用JSON.stringify()
1
2
3
4
5
6
7
8
9
10
|
let obj = {
name: '小明',
age: 20,
job: 'Software Engineer',
friends: ['小花', '小丽']
}
let obj1 = JSON.parse(JSON.stringify(obj));
obj1.friends[0] = '小美';
console.log(obj.friends); // ["小花", "小丽"]
console.log(obj1.friends); // ["小美", "小丽"]
|
缺陷:处理不了function对象、undefined以及symbol类型,原因时JSON.stringify()在处理这些类型,这些类型会被忽略,不会被处理,详情见 MDN
(2)递归,对每层数据实行遍历然后进行拷贝
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
let obj = {
name: {
firstName: '小',
lastName: '星',
},
age: 25,
arr: [{ a: 10 }, { b: 50 }]
}
function copyObj(obj) {
let obj1 = Array.isArray(obj) ? [] : {};
for (const key in obj) {
if (typeof obj[key] === 'object') {
obj1[key] = copyObj(obj[key]);
} else {
obj1[key] = obj[key]
}
}
return obj1
}
let obj2 = copyObj(obj);
obj2.arr[0].a = 80;
obj2.name.firstName = '王';
console.log(obj);
console.log(obj2);
|
(3)Jquery中实现深拷贝
Jquery中实现深拷贝的原理也是递归
1
2
3
4
5
6
7
8
9
10
11
12
|
let obj = {
name: {
firstName: '小',
lastName: '星',
},
age: 25,
sayName() { }
}
let obj2 = $.extend(true, {}, obj);
obj2.name.firstName = '王';
console.log(obj.name.firstName); // 小
console.log(obj2.name.firstName); // 王
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
let obj = {
name: {
firstName: '小',
lastName: '星',
},
age: 25,
arr: [{ a: 10 }, { b: 50 }]
}
let obj2 = _.defaultsDeep({}, obj);
obj2.arr[0].a = 80;
obj2.name.firstName = '王';
console.log(obj);
console.log(obj2);
|