在进入深拷贝和浅拷贝之前先了解一下js中的数据类型
基本数据类型:number、string、boolean、null、undefined
引用数据类型:object、function、array
我们先来看一下简单数据类型的复制
简单数据类型:将a的数据赋值给b,这样是没有问题的。
<script>
var a = 1;
var b = a; // 栈内存会开辟一个新的内存空间,此时b和a都是相互独立的
</script>
再来看一下引用数据类型的复制
引用数据类型不能通过简单赋值而进行复制,因为这样的话两者是存在关联的,改一个的数据另一个的数据也会跟着改变。
<script>
var obj1 = { a: 1, b: 2 };
var obj2 = obj1; // 赋值的内存地址,两者存在关联关系
</script>
浅拷贝(对象/数组):假设B复制了A,当修改A时,如果B也跟着变了,说明这是浅拷贝。本质上,拷贝的是指针(内存)地址。
浅拷贝:适应于简单数据类型。对于复合数据类型(对象/数组),只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。
介绍完浅拷贝概念了,对于简单类型的复制我们大家并不陌生,直接赋值就可以了,但是引用类型的呢?我们来看有这几种方法。
1.使用Object.assign() 用于对象
var person2 = Object.assign({}, person1);
-
无法应用于数组
-
这种方式是浅拷贝的,无法拷贝嵌套对象、嵌套数组
2.JS中拷贝Array的slice和concat方法 用于数组
<script>
let arr = [1, 2, 3, 4];
let new_arr = arr.slice()
</script>
这里只介绍一个slice方法concat方法类似
3.for in 循环浅拷贝 用于对象/数组
<script>
// 适合浅拷贝
var point1 = { x: 0, y: 0 }
// 浅拷贝--es5版
function shallow_copy(obj) {
var copy = {};
for (let key in obj) {
copy[key] = obj[key];
}
return copy;
}
var point2 = shallow_copy(point1);
</script>
4.使用扩展运算符 用于对象/数组
var person3 = { ...person1 };
-
这种方式是浅拷贝的,无法拷贝嵌套对象、嵌套数组
深拷贝:假设B复制了A,当修改A时,如果B没有发生变化,说明这是深拷贝。本质上拷贝的是数据,在内存中重新生成的一份数据。
废话不多说 上代码
1.深拷贝实现方式:JSON方法
<script>
var person6 = {
name: "黄小米",
age: 25,
salary: undefined,
tel: /^1[34789]\d{9}$/,
school: {
name: '泰山学院',
location: '泰安'
},
sleep: function () {
console.log('zzz....')
}
}
var person8 = JSON.parse(JSON.stringify(person6));
</script>
-
这种方式无法拷贝 正则表达式、undefined,function
2.深拷贝实现方式:递归方法
这里就需要自己动脑子写一个了 hh
//使用递归的方式实现数组、对象的深拷贝
function deepClone(obj) {
//判断拷贝的要进行深拷贝的是数组还是对象,是数组的话进行数组拷贝,对象的话进行对象拷贝
var objClone = Array.isArray(obj) ? [] : {};
//进行深拷贝的不能为空,并且是对象或者是数组
if (obj && typeof obj === "object") {
for (key in obj) {
if (obj.hasOwnProperty(key)) {
// 判断是否嵌套对象 判断是否为正则表达式
if (obj[key] && typeof obj[key] === "object" && !(obj[key] instanceof RegExp)) {
objClone[key] = deepClone(obj[key]);
} else {
//函数走这里,因为赋值的不是函数名,而是函数体,所以是深拷贝。和以前函数之间没有联系了!
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
var person9 = deepClone(person6);
这样就实现了深拷贝😎
好了本篇文章就到这里了,喜欢的话可以关注我,会持续更新的,有错误欢迎大佬指出,大家也可以在我这里互相讨论学习,一起进步。
青山不改 绿水长流 下篇文章见