***首先明确浅拷贝和深拷贝针对的都是 引用数据类型,首先明确一下,并不是说浅拷贝不能用,而是要视情况而定,浅拷贝只是拷贝的第一层,遇到多层对象的类型,就需要使用深拷贝了。这里建议复习一下栈和堆的区别,这里就容易理解的多。关于浅拷贝常见的方式这里就简单概括一下
(1)浅拷贝的常见方法
(1)拷贝对象时
当对象里只含有基本数据类型,直接通过 Object.assgin() 或者展开运算符 {...obj}
const obj = {
name :'张三',
age:18,
};
const newobjOne = Object.assign(obj);
const newobjTwo = {...obj};
(2)拷贝数组时
通过Array.prototype.concat() 或者 [...array]
(3)直接赋值和浅拷贝有什么区别?
1. 直接赋值的方法,只要是对象 ,都会互相影响,因为是直接拷贝对象 栈里面的地址。
2. 浅拷贝如果只是一层对象,不会互相影响,如果出现多层对象,那么拷贝就会互相影响。
(4)浅拷贝怎么理解呢?
1.拷贝对象时,里面的属性值如果都是简单数据类型则直接拷贝值,例如这种对象
const obj = {
name :'张三',
age:18,
};
2.如果属性值是引用数据类型,则拷贝的是地址,此时新对象和老对象的引用数据类型,实际上还是指向同一块内存。
const obj = {
name :'张三',
age:18,
//引用数据类型
hobby:['抽烟','喝酒','烫头'],
famliy:{
bro:'李四',
sis:'王五',
}
};
(2)深拷贝的常用的三种方法
(1)递归实现深拷贝
<script>
// 实现深拷贝的三种方式
const obj = {
name :'张三',
age:18,
hobby:['抽烟','喝酒','烫头'],
famliy:{
bro:'李四',
sis:'王五',
}
};
const o = {};
// (1)使用递归实现深拷贝
//拷贝函数
function deepCopy(newobj,oldobj) {
for (const k in oldobj) {
//处理数组问题 一定先判断数组 在判断对象 不能颠倒
//instanceof object 和 instanceof array都是true 先判断对象的话 数组都被当做对象处理了 报错array is not defined
if (oldobj[k] instanceof array) {
newobj[k] = [];
//newobj[k]接收[],hobby,
// 此时oldobj[k] => ['抽烟','喝酒','烫头']
deepCopy(newobj[k],oldobj[k])
// instanceof 判断数据类型 {
// (1) 引用数据类型 ==> false;
// (2) null 和 undefined ==> false;
// (3) array object 和 function ==> true
// }
}else if (oldobj[k] instanceof object) {
newobj[k] = {};
deepCopy(newobj[k],oldobj[k])
}else {
//k 表示属性名 name age ;oldobj[k]表示属性值 张三 18
//newobj[k] === o.name 给对象添加新属性 newobj[k] = oldobj[k] 给新属性赋值
//为什么不用newobj.k 呢 ?
//此时相当于给o 添加了一个名为k的属性 后面就不会再循环了 而这里k是变量,所以只能用newobj[k]的写法
newobj[k] = oldobj[k];
}
}
}
deepCopy(o,obj)
console.log(o);
console.log(obj);
</script>
(2)利用js库 lodash 里面的 cloneDeep 内部实现深拷贝
//(1)先引入
<script type="text/javascript" src="https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)"></script>
const c = _.cloneDeep(obj)
(3)利用 json 字符串转换
JSON.stringify() 把对象转换为JSON字符串 (转为基本数据类型)
JSON.parse() 把JSON 字符串转换为json对象 (转为对象,开辟新空间)
const d = JSON.parse(JSON.stringify(obj))