前提知识
见博客:原始值和引用值
例子
老师布置了一份论文,好学生的论文中还引用了他之前写的博客,也就是说
//好学生A
A_Homework = {
content:'论证1+1证明过程,见博客:',
blog:{
content:'因为2=1+1,所以1+1=2'
}
}
浅拷贝1
坏学生B:一把抢过了A的作业本,在名字那一栏由加上了自己的名字(变成小组作业)
B_Homework = A_Homework
所以此时A和B和作业就是同一个作业,都可以修改作业内容和博客内容,且都会造成影响
这时B在作业本第一行加了一句
B_Homework.firstCuntent='这是A和B的小组作业'
这个时候我们可以发现A的作业本也加了这一句(因为他们本来就是一本作业)
console.log(A_Homework.firstCuntent)
输出:这是A和B的小组作业
浅拷贝2
B终于良心发现,意识到直接占领别人的劳动成果是不对,于是B把A的作业抄了一遍
B_Homework={}
B_Homework.content = A_Homework.content
但是B抄到一半发现还要引用博客内容,B偷懒就直接写了A的博客地址
B_Homework.blog = A_Homework.blog
此时B作业本的内容是B的,不是A的,所以A和B修改content不会影响到对方
B_Homework.content = '我是B,我的论证过程见博客:'
这个时候我们可以看一下A的作业内容受到影响了吗
console.log(A_Homework.content)
输出:论证1+1证明过程,见博客:
但是如果B顺着A的博客地址改变了A博客的内容,A会受到影响
B_Homework.blog.content='我是B,我的论证过程是:因为2=1+1,所以1+1=2'
console.log(A_Homework.blog.content)
输出:我是B,我的论证过程是:因为2=1+1,所以1+1=2
深拷贝
B终于大彻大悟,意识到即使抄,也要完完整整的抄
于是B既在自己的作业本上抄了A的内容,又在自己的博客上抄了A的博客
B_Homework={}
B_Homework.content = A_Homework.content
B_Homework.blog={}
B_Homework.blog.content = A_Homework.blog.content
此时B修改他自己的博客会影响A吗
B_Homework.blog.content = '我是B,我不会'
console.log(A_Homework.blog.content)
输出:因为2=1+1,所以1+1=2
此时B终于彻彻底底的写了一份自己的作业,再也不会影响A
总结
原因
以浅拷贝1为例
- js对引用值的存储是只存地址
- 所以在拷贝引用值时只会将A的地址赋给B
- 这就导致有A和B指向一块内存空间(可以理解为A和B就是同一个东西,就像小明的小名叫二蛋,那么“小明”和“二蛋”其实都是一个人)
浅拷贝和深拷贝的区别
浅拷贝只拷贝了对象的部分属性,而深拷贝则递归拷贝了所有层级。
- 浅拷贝:部分属性只拷贝了地址
- 深拷贝:重新拷贝了一整个东西
- 通俗点:浅拷贝是给小明起了个小名;深拷贝是制造了一个小明的复制人
- 体现为:浅拷贝会使二者相互影响,深拷贝则因为二者相互独立不会受到影响
赋值与浅深拷贝
在弄清楚这块内容之前,我一直认为赋值,浅拷贝,深拷贝是三个同层级的东西:
- 赋值是直接A=B
- 浅拷贝是将A的1到(n-1)个属性的值赋给B
- 深拷贝是将A的所有n个属性的值赋给B
但在写博客的时候才发现,赋值,浅拷贝,深拷贝不是同层级的东西:
- 赋值是手段,是过程
- 浅拷贝,深拷贝是最终实现的效果
- 浅拷贝,深拷贝的实现都是通过赋值(=)
- 可以把赋值比作学习,那么浅拷贝就是没学好,深拷贝就是学的很好