js浅复制的新对象属性

问题描述

浅复制是复制引用,复制后的引用都是指向同一个对象的实例,彼此之间的操作会互相影响,下面例子中我新建一个obj对象,然后浅复制了一个新对象newObj出来,为什么我操作obj里面的数组arr,新对象newObj会有变化,而我直接修改obj.name属性,新对象newObj却没有变化,

问题出现的环境背景及自己尝试过哪些方法

相关代码

//浅复制
                function simpleClone(obj){
                   var simpleCloneObj = {};
                   for(var item in obj){
                     simpleCloneObj[item] = obj[item]  
                   }
                   return simpleCloneObj
                }
                
                var obj = {
                  name:"dabao",
                  age:28,
                  arr:[1,3,5]
                }
                
                var newObj = simpleClone(obj);
                
                obj.arr.push(0);
                obj.name = 'hello';
                console.log(newObj);
                console.log(obj);

你期待的结果是什么?实际看到的错误信息又是什么?

我理解的浅复制,是新对象被浅复制出来后,原对象的属性值得改变都会在复制出来的新对象里面有体现,不知道为什么属性没有变化?

阅读 2.7k
4 个回答

你写的方法相当于 newObj.name = obj.name
name,age是字符串,数字 是基本类型 所以复制的是值不是引用
arr不是基本类型 所以复制的是引用

想实现你说的 修改一个改变另一个 直接 newObj = obj 就行了

因为name是一个值不是一个引用,浅复制是指:

let p={
    name:"123",
    ch:[1,2,3,4],
}

let k= p;
k.name="456"
//此时p.name也会变成456

如图:clipboard.png

而在你的simple Clone这个函数当中,你并没有对这个对象进行操作,而是操作了对象的属性。
对于其中的某一个属性进行了复制,这就相当于

let a = "123";
let b = a;
b = "456";
//不会影响a

当然,如果这个属性本身还是一个引用的话比如数组或者对象,那么他才会依然是一个浅复制

属性没有变化,是因为属性值是属于值类型的变量,而数组和对象都是属于引用类型的变量,其实深复制和浅复制都是围绕内存地址这个问题来进行的,而内存地址和变量的属性(引用类型还是值类型)是分不开的。你的方法,循环复制里面,arr是个数组,赋值也只是把内存地址赋值过去了,真正的值并没有赋值过去。
你这种复制方法,虽然循环了一层,但是还是属于浅复制,真正深复制请参考jQuery的$.extend方法,递归的去复制,这才是真正的深复制。

1.首先,你在simpleClone()这个函数里创建了一个新对象,newObj和初始的obj指向的是两个地址;
2.原始obj的name和age是原始类型=操作的时候是赋值的真真正正的值,arr是一个引用类型,当执行=操作的时候,是把原始obj的arr的地址复制给了newObj的arr属性。
3.所以name和age与原来没有关联了,而arr还与原来的obj还是指向的同一份数据的地址

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题