2011-03-29 65 views
0

我在我的模型中有一些值存储。我需要创建这些值的副本,进行一些更改,然后输出这些更改而不影响模型值。Adob​​e Flex ActionScript防止模型污染

var my_source:Array = model.something.source 
var output:Array = new Array(); 

for each (var vo:my_vo in my_source) { 
    if (vo.id == 1) { 
     vo.name = 'Foo'; 
     output.push(vo); 
    } 
    else if (vo.id == 21) { 
     vo.name = 'Bar'; 
     output.push(vo); 
    } 
} 
return output; 

因此,这工作正常,除了循环通过my_source时所做的任何更改似乎也影响model.something。为什么更改my_source数组会影响模型?我如何防止这种情况发生?

回答

1

我已经mentioned how to do this in my blog,但简短的回答是使用ObjectUtil.copy() 。因为Flash使用基于引用的对象,所以你只是在不复制,所以你只能将引用复制到另一个数组中。通过使用ObjectUtil.copy(),你正在做所谓的“深层复制”,它实际上是在新的内存位置重新创建对象。

+0

对于'ObjectUtil.copy()'+1。打败我的串行器/解串器方法:) – 2011-03-30 01:59:41

+0

@布莱恩,这是一个好主意。你的序列化程序本质上就是ObjectUtil.copy所做的:) – 2011-03-30 14:24:19

0

您正在处理对数据的引用,而不是数据的副本。这就是ActionScript-3(和许多其他语言)的工作原理。

当您创建my_source变量时,您将创建对model.something.source的引用,该引用还包含对模型对象的所有引用。此外,当您循环访问my_vo对象时,您还将获得对这些对象的引用。这意味着如果您在此循环中对对象进行更改,则会更改模型中的对象。

你如何解决这个问题?在你的循环内,你需要制作一个你的对象的副本。我不知道my_vo是什么样子,但是如果在对象树中有其他对象,它们也会是引用,这可能需要“深度复制”才能实现所需。

实现“深层复制”的最简单方法(但通常不是最有效的方法)是序列化和反序列化。一种方式来实现这一目标:

function deepCopy(source:Object):* { 
    var serializer:ByteArray = new ByteArray(); 
    serializer.writeObject(source); 
    serializer.position = 0; 
    return serializer.readObject(); 
} 

然后,在你的循环,你可以让你的数据副本:

for each(var vo:my_vo in my_source) { 
    var copy:my_vo = deepCopy(vo); 

    // act on copy instead of vo 
}