属性都具有原始值的对象的副本是否同时符合深副本和浅副本的定义? [已关闭]

问题描述 投票:0回答:1

来自 developer.mozilla.org/“深层复制”页面

属性都具有原始值的对象的副本既符合深复制又符合浅复制的定义。

我不确定我是否理解这句话。

下面是一个片段,我使用

x
值创建一个实体
'hello'
,然后通过
y
将其分配给另一个新变量
y = x
。来自另一种语言,我想知道
y
x
是否是独立的,或者改变一个会影响另一个。从执行代码的结果来看,我明白它们是无关的。

x = 'hello';
y = x;
y = 'world';

console.log(x)
console.log(y)

但是,如果

x
是一个对象,例如
{ k: 'v' }
,那么看起来
y = x
定义了
y
,它基本上只是
x
的别名:

x = { k: 'v' }
y = x;
y.k = 'w';

console.log(x)
console.log(y)

在后一个片段中,

x

的描述不匹配

属性都具有原始值的对象

假设它只有一个与字符串值

'v'
关联的属性?

如果是这样的话,那么上述引用对于后者意味着什么

x

javascript deep-copy shallow-copy
1个回答
0
投票

变量赋值不是复制,是引用。复制是指创建具有相同属性且每个属性具有相同值的新对象。

变量可以是基元或对象。原语是“字符串”、“数字”和“布尔值”,也请保持简短。在 javascript 的对象类别中,几乎所有非原语的东西都属于对象类别,如数组、函数等。

当您将原语分配给变量时,该变量会将内存中的位置保存为该值。当您将源变量的值分配给新变量时,内存中会出现一个具有相同位的新空间,并且新变量保存指向内存中新位置的指针。所以:

var a = "something"; //lets say this is the source var 
var b = a;  //this will create a copy of a. When you change b, a is not affected

对于任何其他原语也是如此。

对于物体来说,故事完全是另一回事。对象通过引用保存在内存中,当您从另一个变量分配新变量时,它们将指向内存中相同的精确位置。

var a = { foo:"bar" }
var b = a; //this will point to the same exact object. when you change b.foo = "new" then also a.foo will be equal to "new" because is the same object. 

这个逻辑也适用于对象内部属性的嵌套。数组将其视为一个特殊的对象,其键是连续的数字,并通过名为 length 的属性来跟踪元素的数量。因此,当您听到数组时,也会想到参考值。

现在考虑以下事项:

var sourceObj = {
    prop1 : 123,
    prop2 : "something"
    prop3 : {
       foo: "bar" 
    },
    prop4 : [1,"2",{key:3},[10,20,30]]   //this has it all kinds 
}

var newObjReference = sourceObj; //this case is clear as it would be identical to access anything from sourceObj.propX same as newObjReference.propX 

现在将对象视为该属性的容器,是声明一些变量的地方。 (为了清楚起见,我在这里过于简单化了)。

浅拷贝只会创建一个具有与原始对象(sourceObj)相同的 props 的新容器,但内部的其他所有内容都遵循上面解释的相同 valueType 和 referenceType 规则。

var shallowManualCopy = {
   prop1: sourceObj.prop1, //this will be copied as it is a primitive 
   prop2: sourceObj.prop2, //same with this will be copied
   prop3: sourceObj.prop3, //this will reference the same identical object that sourceObj.prop3 has because it is an object. remember the part above
   prop4: sourceObj.prop4 //same with the array. it will reference the same identical array not a copy, but THAT array. 
}

所以如果我更改shallowManualCopy.prop1,那么sourceObj.prop1将不会受到影响。与 prop2 相同。但另外,如果为shallowManualCopy.prop3分配一个新值,那么sourceObjc.prop3将不会受到影响,因为我们只是更改新对象(新容器)内的prop。

但是:

如果我更改shallowManualCopy.prop3.foo =“new”,那么sourceObj.prop3.foo也将是“新”,因为它们是同一个对象。与数组的任何元素相同。如果我将shallowManualCopy.prop4[2]更改为“somethingElse”,那么sourceObj.prop4[2]将是“somethingElse”

现在深层副本(手动制作以解释)将类似于:

var deepManualCopy = { //a new object container
    prop1: sourceObj.prop1, //this will be copied as it is a primitive 
    prop2: sourceObj.prop2, //same with this will be copied
    prop3: { //another new object 
       foo: sourceObj.prop3.foo, //this is primitive. so will copy
    },
    prop4: [ //a new array
       sourceObj.prop4[0], //primitive
       sourceObj.prop4[1], //primitive 
       { // another new object 
         key: sourceObj.prop4[2].key, //primitive 
       },
       [ //another new array 
           sourceObj.prop4[3][0], //primitive
           sourceObj.prop4[3][1], //primitive
           sourceObj.prop4[3][2], //primitive
       ]
    ]
}

TL;博士;

要在 javascript 中进行深度复制,您必须使用 StructuredClone(sourceObject) 或 JSON.parse(JSON.stringify(sourceObject)) 对于可序列化对象。

可序列化对象是指内部没有循环引用或不可序列化属性(如函数)的对象(过于简单化)

浅拷贝是一个新对象(不是同一个对象),但包含所有属性(如 sourceObject)以及 sourceObject 中的所有值(如果不是基元)作为引用。

我希望你能从这一切中学到一些东西。

© www.soinside.com 2019 - 2024. All rights reserved.