关于浅拷贝的一些疑问,希望大佬们帮忙辛苦答疑解惑。

Aa狸烤鱼豆腐猫 2021-04-29 10:50:32

<script>
var obj = {
id: 1,
name: 'haha',
ob: {
id: 23
}
}
var o = {}
for (var k in obj) {
// obj[k]表示属性值,k表示属性名
// o[k]表示什么,也是表示属性值?那是如何进行拷贝的呢?
o[k] = obj[k];
}
o.id = 5;
o.ob = {
id: 66
}
console.log(o)
console.log(obj)

以上代码块对obj进行浅拷贝并复制给o对象,不是说浅拷贝只是复制地址,专业点叫复制引用,更改其中一个对象中的复杂数据类型之后,另一个对象中的相关数据也会发生改变吗,但是为何以下代码更改了其中一个对象中的复杂数据类型,另一个对象中的复杂数据类型不受影响。比方说更改了o.ob的数据但是obj.ob不受影响。

o.ob = { id: 66 }

下图是更改 o.ob = { id: 66 }的运行结果


除非像以下这种更改,obj.ob中的数据才会受影响。这是为何呢?

o.ob.id = 66;

望大佬指点迷津,谢谢。
...全文
173 6 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
引用 5 楼 泡泡鱼_ 的回复:
[quote=引用 4 楼 Aa狸烤鱼豆腐猫 的回复:]我把o.ob = { id:23}修改为o.ob = { id:666},这样不也修改了第二层级吗
你改的就只是ob。你别被里面那个什么id给影响。你操作的是ob。和里面id没有必然联系,就只是你自己刚好又给了个同名的属性id而已。你如果o.ob={xxx:'yyyy'}呢?这下总没id了吧。你认为obj.ob成啥了?原样呗。你浅拷贝过了呀,第一层的ob直接操作,重新赋值。都和obj没半毛钱关系了呀。你自己仔细想想吧 前面有说过,你直接:o={ id: 1, name: 'haha', ob: { id: 23 } }。难道它和obj有关系?没有的。 你浅拷贝后,o.ob对象本身已经和obj没关系了[/quote] 好的谢谢大佬,我自己再想想。
泡泡鱼_ 2021-04-30
  • 打赏
  • 举报
回复
引用 4 楼 Aa狸烤鱼豆腐猫 的回复:
我把o.ob = { id:23}修改为o.ob = { id:666},这样不也修改了第二层级吗
你改的就只是ob。你别被里面那个什么id给影响。你操作的是ob。和里面id没有必然联系,就只是你自己刚好又给了个同名的属性id而已。你如果o.ob={xxx:'yyyy'}呢?这下总没id了吧。你认为obj.ob成啥了?原样呗。你浅拷贝过了呀,第一层的ob直接操作,重新赋值。都和obj没半毛钱关系了呀。你自己仔细想想吧 前面有说过,你直接:o={ id: 1, name: 'haha', ob: { id: 23 } }。难道它和obj有关系?没有的。 你浅拷贝后,o.ob对象本身已经和obj没关系了
  • 打赏
  • 举报
回复
我把o.ob = { id:23}修改为o.ob = { id:666},这样不也修改了第二层级吗
  • 打赏
  • 举报
回复
感谢大佬耐心解答,看了您的解释我还是不太明白,可能还没开窍,烦您再点拨点拨。

       o.ob = {
            id: 66
        }

o.ob.id = 66;
以上两种方式都是修改了o对象中的相关属性值,但是只是第二种方式能同步更改obj里面的数据,而第一种却不行,同样都是修改了id为何就会不一样呢,能否从更深的角度去解释一下,听您这样解释还是不太明白。另外,您说的浅拷贝是切断了第一层的引用关系,是否能理解成或者换句话说浅拷贝是完全复制简单数据类型的内存空间,而复杂数据类型只是复制内存空间的地址。
泡泡鱼_ 2021-04-30
  • 打赏
  • 举报
回复
看你说的大概也是有点理解的。但浅拷贝,这个浅字,就表现在,它只是切断了对象的第一层的引用关系。你把obj当成树看,紧挨着主干的那一波,就是层级为1,然后再延展出去的,层级就依次增加。 在你这个例子中,id,name,ob都是obj的第一层级的属性,所以,你直接,注意,我说的是“直接”对它们做修改,都不会影响到obj,因为你在浅拷贝时,简单的说,它们已经是属于o的了,和obj对象本身不存在引用关系。所以,你o.ob=任何值,都不会影响到obj 当你未对o.ob做修改的前提下,你直接修改o.ob.id的值,它是会对obj中相同路径的属性同步修改的。因为o.ob.id已经是第二层级的了。之前的浅拷贝切断引用关系,对它是无效的。

o.id = 5;
        o.ob = {
            id: 66
        }
o.ob.id=88
        console.log(o)
        console.log(obj)
不过,像上面这样,你如果先操作o.ob={id:66},然后再o.ob.id=任意值,这个时候对obj是没有影响的。o.ob={id:66}重新赋值,它就已经和obj中的ob没有任何关系了,只是大家属性名称一样而已。这个就好比说,你直接定义o={ id: 1, name: 'haha', ob: { id: 23 } }。虽然它看着和obj一模一样。但很明显,你马上就知道它是一个新对象,和obj是没有关系的

o = obj

o = { id: 1, name: 'haha', ob: { id: 23 } }
o.ob.id = 98
就好比这样,如果没有中间那句对o的重新赋值定义。下面的o.ob.id是会影响到obj的。但加上中间那句,你怎么改都和obj没毛线关系了
weixin_37226778 2021-04-30
  • 打赏
  • 举报
回复
 o.ob = {
        id: 66
    }
这一步你给ob赋值了一个新对象啊,虽然和原来的长的一样,但它是一个新的对象

87,997

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧