这是我参与更文挑战的第18天,活动详情查看: 更文挑战
前言
深拷贝与浅拷贝在前端项目开发过程中,使用频率、实用性都很高的一个小工具函数了。
针对不同的业务场景,可以选择的写法也有不少。
简单的可以直接写个浅拷贝, 复杂的又根据不同的参数,处理方法也会不一样。
所以简单的讲讲深浅拷贝吧。
前置知识
不过,在写深浅拷贝之前,我们是不是得先知道下,为什么要写深浅拷贝呢?直接赋值拷贝不行吗?
为什么要写?
在JavaScript中, 有两大类数据类型:基本类型、引用类型。
基本类型:常见的如数字、字符串、布尔值等都属于基本类型,这类数据类型在内存中占据固定大小,保存在栈内存中。
引用类型:我们常用的数组、对象都属于引用类型,保存在堆内存中,而堆内存中存储的是目标的存储地址。
两种类型的区别在于:
如果一个变量存储的基本类型,那么将该变量赋值给另一个变量时,执行的复制操作。
如果是引用类型,那么该变量与被赋值的变量,操作的是同一个数组、对象。
看个例子:
var a = 1;
var b = a;
a = 2;
console.log(a); // 2
console.log(b); // 1
var arr1 = [1,2,3];
var arr2 = arr1;
arr1.push(4);
console.log(arr1); // [1,2,3,4]
console.log(arr2); // [1,2,3,4]
复制代码
可以看到,基本类型赋值之后,互不影响。 而引用类型则是貌离神合。
在实际业务开发中,如果需要复制一份引用类型的数据的话,操作数据会影响另一个变量可就太容易出事了。
所以,就回答了前面的问题,为什么要写深浅拷贝。
浅拷贝
前面已经聊完了为什么要写拷贝工具函数,那么这里就进入正文,先看看浅拷贝的几种方式;
1、数组:Array.slice() 针对数组的浅拷贝
let a = [1,2,3,4]
let b = a.slice();
a.push(5);
console.log(a); // -> [1, 2, 3, 4, 5]
console.log(b); // -> [1, 2, 3, 4]
复制代码
2、数组:Array.concat()
let a = [1,2,3,4]
let b = a.concat();
a.push(5);
console.log(a); // -> [1, 2, 3, 4, 5]
console.log(b); // -> [1, 2, 3, 4]
复制代码
3、对象:Object.assign() 对象浅拷贝
let obj = {name: 'Corey'}
let obj2 = {};
Object.assign(obj2, obj); // 对象obj的值会覆盖obj2中重复的值;obj2中没有,则新增进去。
obj.age = 18;
console.log(obj); // {name: 'Corey', age: 18}
console.log(obj2); // {name: 'Corey'}
// 简写
let obj2 = Object.assign({}, obj);
复制代码
深拷贝
浅拷贝应对的情况比较单一,但是如果通过函数结合起来,自动判断数据类型,并响应的执行拷贝是不是就会强大起来呢?
这里介绍两种写法。
1、数组、对象混合的情况
主要借助JS的函数,JSON.parse() 解析json, 以及JSON.stringify()转JSON函数;
将元数据转为字符串,再重新解析为可操作性的数据,就将数据复制出来一份了,并且不会改变元数据。
let data = [
1,2,3
{name: 'corey', age: 12}
]
let dataCopy = JSON.parse(JSON.stringify(data));
复制代码
2、手动实现一个深拷贝
前面的写法过于简单粗暴了?那这里就手动实现一个吧? 为什么有简单的,还要自己折腾一个呢?
为了耍帅?NoNoNo,当然不是, 在JS中,还有很多其他类型,例如函数Function,函数是无法通过上面的方式直接实现拷贝的, 所以手动实现虽然相对麻烦一些,但是更灵活。
let obj = {
name: 'name',
age: 23,
info: {
desc: 'hello'
},
color: ['red','green','blue']
};
let obj2 = {};
function deepClone(res, source){
for(let key in source){
let item = res[key];
if(item instanceof Array){
res[key] = [];
deepClone(obj[key], item)
} else if(item instanceof Object){
res[key] = {};
deepClone(res[key], item);
} else {
res[key] = item;
}
}
}
deepClone(obj2, obj);
复制代码
总结
太困了太困了, 今天就写到这里。
希望能帮助到各位小伙伴。
有什么疑问、或者想要讨论的都可以在评论区留言讨论哦。