Javascript JS:Object.assign()是创建深度副本还是创建浅层副本

Javascript JS:Object.assign()是创建深度副本还是创建浅层副本,javascript,object,deep-copy,shallow-copy,Javascript,Object,Deep Copy,Shallow Copy,我只是偶然发现了这个概念 var copy = Object.assign({}, originalObject); 它将原始对象的副本创建到“copy”对象中。然而,我的问题是,这种克隆对象的方式是创建深度副本还是创建浅层副本 PS:混淆的是,如果它创建了一个深度副本,那么这将是克隆对象的最简单方法。忘记深度副本,即使是浅层副本也不安全,如果您要复制的对象的enumerable属性设置为false MDN: assign()方法只复制可枚举和自己的属性 从源对象到目标对象 就拿这个例子来说

我只是偶然发现了这个概念

var copy = Object.assign({}, originalObject);
它将原始对象的副本创建到“
copy
”对象中。然而,我的问题是,这种克隆对象的方式是创建深度副本还是创建浅层副本


PS:混淆的是,如果它创建了一个深度副本,那么这将是克隆对象的最简单方法。

忘记深度副本,即使是浅层副本也不安全,如果您要复制的对象的
enumerable
属性设置为false

MDN:

assign()方法只复制可枚举和自己的属性 从源对象到目标对象

就拿这个例子来说

var o = {};

Object.defineProperty(o,'x',{enumerable: false,value : 15});

var ob={}; 
Object.assign(ob,o);

console.log(o.x); // 15
console.log(ob.x); // undefined

通过使用Object.assign(),您实际上是在对对象进行浅拷贝。每当我们执行诸如将一个对象指定给另一个对象之类的操作时,我们实际上会执行浅复制,即,如果OBJ1是一个对象,则通过另一个对象OBJ2对其进行修改也会反映OBJ1中的更改。

它会创建浅复制,具体如下所示:

对于深度克隆,我们需要使用其他替代方法,因为 assign()复制属性值。如果源值是 引用对象时,它仅复制该引用值


对于redux来说,
Object.assign()
就足够了,因为redux应用程序的状态只包含不可变值(JSON)。

对于小型
数据结构
我发现
JSON.stringify()
JSON.parse()
工作得很好

// store as JSON
var copyOfWindowLocation = JSON.stringify(window.location)
console.log("JSON structure - copy:", copyOfWindowLocation)
// convert back to Javascript Object
copyOfWindowLocation = JSON.parse(copyOfWindowLocation)
console.log("Javascript structure - copy:", copyOfWindowLocation)

其他答案很复杂。
有些人根本不回答这个问题

下面是我的工作

// orignal object with deep keys
var originalObject = {
    k1: "v1",
    k2: "v2",
    deepObj: {
        k3: "v3",
        k4: "v4"
    }
};

// make copies now
var copy1 = JSON.parse(JSON.stringify(originalObject));
var copy2 = JSON.parse(JSON.stringify(originalObject));
希望有帮助

var copy = Object.assign({}, originalObject);
正在更改副本的浅层副本是否也反映了原始对象中的更改。因此,要执行深度复制,我建议使用
lodash
cloneDeep

import cloneDeep from 'lodash/cloneDeep';
var copy = cloneDeep(originalObject);

如上所述,
Object.assign()
将执行浅层克隆,无法复制源对象的自定义方法,并且无法使用
enumerable:false复制属性

保留方法和不可枚举属性需要更多的代码,但不需要更多

这将执行数组或对象的浅层克隆,复制源的方法和所有属性:

函数浅克隆(src){
设dest=(数组的src instanceof)?[]:{};
//复制源的原型
setPrototypeOf(dest,Object.getPrototypeOf(src));
Object.getOwnPropertyNames(src.forEach)(名称=>{
常量描述符=Object.getOwnPropertyDescriptor(src,name);
Object.defineProperty(dest、name、descriptor);
});
返回目的地;
}
例如:

类自定义扩展对象{
myCustom(){}
}
const source=new Custom();
source.foo=“这是foo”;
Object.defineProperty(来源,“nonEnum”{
值:“不枚举”,
可枚举:false
});
Object.defineProperty(来源,“非写”{
值:“不写”,
可写:false
});
Object.defineProperty(来源,“非图”{
值:“不配置”,
可配置:false
});
让克隆=浅克隆(源);
log(“source.nonEnum:”,source.nonEnum);
//source.nonEnum:“不枚举”
log(“clone.nonEnum:”,clone.nonEnum);
//clone.nonEnum:–“不枚举”
log(“typeof source.myCustom:”,typeof source.myCustom);
//typeof source.myCustom:–“函数”
log(“typeof clone.myCustom:”,typeof clone.myCustom);
//clone.myCustom的类型:–“函数”

doc是不言自明的,我想:“Object.assign()方法用于将所有可枚举自身属性的值从一个或多个源对象复制到一个目标对象”Lodash的z.clonedeep进行深度复制,并按预期工作如果它只进行浅层复制,Redux如何工作?我认为它的全部意义在于对发送的数据进行深度复制,这样,如果数据在存储区之外发生更改,也不会更改存储区中的内容。如果它是一个浅层副本,那么数据将被链接,这会导致数据在没有分派的情况下更改存储中的内容时出现问题,对吗?我在Redux中遇到了同样的问题,最后转到JSON.parse(JSON.stringify())。如果对象被另一个包变异并产生递归问题,这也会出现问题。我正在寻找一个更好的选择。此方法仍然是我正在使用的方法。应用程序的redux状态不能包含引用其他对象的对象吗?@VictorZamanian它肯定可以,因此Object.assign可能不是正确的工具,具体取决于数据结构。我发现对Redux州特别有用。它只对您更改的内容执行深度复制,并对其他所有内容使用浅层复制。您的解决方案对我非常有用。直到我读到这个简单的stringify和parse-back解决方案,我才感到沮丧。非常感谢,太好了!我很高兴这有助于你谨慎行事<代码>JSON.stringify()。。。JSON.parse()。它会将原始对象的任何“类型”转换为普通对象。这并不能完全回答这个问题。而是说如果它是不可枚举的,将会发生什么。