0

我正在使用 underscore.js 库有一个克隆方法。

var newObject = _.clone(oldObject);

我从其中一个评论中读到它是一个浅克隆。我想克隆一个对象并将其传递给不同的函数。

当我更改内部的 newObject 时function A(),我得到以下结果...

{
    'Des': 'Some Des'
    'Des1': 4,
    'Des2': {
        "ChildDes": 0,

    },
},

但是,当我将作为克隆对象的 newObject 传递给另一个function B()时,我得到的警报值为[Object,Object]. 为什么?我无法打印这样的值..

function B(newObject){
   alert(newObject.Des2);
}
4

2 回答 2

4

“浅拷贝”是一个拷贝,它只拷贝所有成员。如果其中一个成员是对对象的引用,则复制引用的更改将影响原始引用。“深拷贝”也将复制对象,因此对深拷贝元素的更改不会影响原始对象。有时很难实现深拷贝,因为对象成员可能对对象本身有引用。

玩一点不同的复制风格,看看会发生什么。另请参阅:clone() 一个对象是什么意思?

于 2012-06-03T09:31:14.917 回答
0

术语“浅拷贝”和“深拷贝”的使用不一致,恕我直言,应避免使用。我建议将克隆操作分为三类:

  1. 对于以保存各种对象为目的的事物(例如“SuperDuperList”),公共克隆方法的行为应该是创建原始类型的新实例,该实例与原始类型保持相同的实例,但与其分离。对原始或克隆对象所做的任何事情都不会影响另一个对象存在的东西的身份。请注意,虽然 `SuperDuperList` 可能有一些 `T[]` 类型的私有字段,但 `SuperDuperList` 的目的不是保存`T` 的数组,而是保存实例的`T`。因此,“SuperDuperCollection”的正确克隆方法必须用新数组替换任何可变数组,这些数组与原始数组具有相同的“T”实例,但与它们分离。有些人将这种类型的副本称为“浅拷贝”,但有些人将该术语用于下面的#2“损坏的副本”语义。有人称其为“深拷贝”,但有些人——包括我自己——会将该术语限制为使用 #3。我更喜欢术语“语义级副本”。
  2. 一些损坏的克隆方法使原始对象和克隆对象都持有对共享对象的引用,从原始对象的角度来看,共享对象是可变的。请注意,从“SuperDuperList”的角度来看,“T”类型的存储位置不包含对可能可变对象“T”的引用,而是包含“T”的不可变标识。另一方面,如果 `SuperDuperList` 有一个包含对 `T` 数组的引用的字段,并且该数组将永远被变异,那么一种克隆方法可以让原始对象和克隆对象保持对相同的引用阵列将被破坏。
  3. 一些克隆方法要求被克隆对象持有的对象必须满足某些特殊标准,以便它们本身可以被克隆(最典型的是,每个嵌套对象的每个属性都必须是不可变的或提供克隆方法)。在某些情况下,这些对象的集合可能并不确切知道这些对象是什么或它们的克隆方法实际上做了什么;如果集合的克隆操作的语义比它对存储在其中的对象的理解更深入,那么这样的集合是可深度克隆的。

派生对象的克隆方法的正常模式应该是首先克隆其父对象,然后克隆任何包含对外部对象的引用的字段,这些外部对象包含被克隆的对象应该包含的内容,并且不能依赖这些内容来保存那些同样的事情永远。如果每个派生类都遵循该模式,则将实现适当的语义级克隆。

于 2012-06-22T17:47:33.137 回答