13.11.1 问题
需要拷贝一个索引数组里的所有项或者从一个对象创建一个新对象。
13.11.2解决
使用mx.utils.ObjectUtil.copy方法
13.11.3讨论
正如演示那样,copy一个对象仅仅是为新对象创建了一个指针。意味着对第一个对象值的任何改变都会反映到第二个对象上。
{name:"foo", data:{first:"1", second:"2"}};
var objTwo = objOne;
objOne.data.first = "4";
trace(objTwo.data.first);//traces 4
相反如果我们想要copy一个对象的全部到另一个对象中,使用mx.utils.ObjectUtil类的copy方法。该方法接受一个对象做为参数而返回一个在内存的新位置的此对象的深度拷贝。
这就意味着该对象的任何属性被copy而不再是引用原始对象相同位置的属性。如下使用此方法:
ba.writeObject(objToCopy);
ba.position = 0;
var objToCopyInto:Object = ba.readObject();
return objToCopyInto;
这样原来的例子就可以如期的执行:
var objTwo = objOne;
var objThree = mx.utils.ObjectUtil.copy(objOne);
objOne.data.first = "4";
trace(objTwo.data.first);//traces 4
trace(objThree.data.first);//traces 1, which is the original value
为了反序列化此数据对象,该类型必须通过flash.net.registerClassAlias方法向Flash Player注册。此方法注册该类,以便该类的实例对象都可以从二进制反序列化回原对象。
registerClassAlias 需要2个参数:
在这里的例子中,拷贝对象时既不知道全类名也不知道该类的一个引用。幸运的是,flash.utils.getQualifiedClass会返回参数传入的对象的全类名,而flash.utils.getDefinitionByName
返回传入的对象的类引用。通过使用这2个方法,你可以注册任何对象的类:
{
if(registerAlias) {
var className:String = flash.utils.getQualifiedClassName(objToCopy);
flash.net.registerClassAlias(className,
(flash.utils.getDefinitionByName(className) as Class));
}
return mx.utils.ObjectUtil.copy(objToCopy);
}
var newArray:Array = new Array();
for(var i:int; i<arr.length; i++) {
newArray.push(copyOverObject(arr[i], true));
}
return newArray;
}
var ac:ArrayCollection = new ArrayCollection([{name:'Joseph', id:21}, foo,
{name:'Josef', id:81}, {name:'Jose', id:214}]);
var newAC:ArrayCollection = new ArrayCollection(copyOverArray(ac.source));
把该集合中一个对象强制转化为某一指定类型都将导致一个错误或空值。
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="alertObj();">
<mx:Style>
Application{fontSize:12px;}
</mx:Style>
<mx:Script>
import mx.controls.Alert;
public function alertObj():void
{
var objOne:Object ={name:"张三", data:{first:"张", second:"三"}};
var objTwo:Object = objOne;
objOne.data.first = "李";//对原始对象的修改,也会在新对象反应出来
Alert.show(objTwo.data.first);//输出 李
}
</mx:Script>
</mx:Application>
<!--对象的深度拷贝-->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="alertObj();">
<mx:Style>
Application{fontSize:12px;}
</mx:Style>
<mx:Script>
import mx.controls.Alert;
import mx.utils.ObjectUtil;
public function alertObj():void
{
var objOne:Object ={name:"张三", data:{first:"张", second:"三"}};
var objTwo:Object =ObjectUtil.copy(objOne);//关键代码
objOne.data.first = "李";//对原始对象的修改,不会影响第二个
Alert.show("objOne="+objOne.data.first+"\nobjTwo="+objTwo.data.first);//
}
</mx:Script>
</mx:Application>
<!--特定类对象的深度拷贝-->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="alertObj();">
<mx:Style>
Application{fontSize:12px;}
</mx:Style>
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.utils.ObjectUtil;
import mx.collections.ArrayCollection;
public function alertObj():void
{
var zl:Object={name:"赵六",age:29};
var ac:ArrayCollection = new ArrayCollection([
{name:'张三', age:20},
zl,
{name:'李四', age:31},
{name:'王五', age:27}
]);
var newAC:ArrayCollection = new ArrayCollection(copyOverArray(ac.source));
//可以如下验证下
//ac[2].name = "改变";
//Alert.show(newAC[2].name);
}
//对一个对象数组深度拷贝
private function copyOverArray(arr:Array):Array {
var newArray:Array = new Array();
for(var i:int;i<arr.length; i++){
newArray.push(copyOverObject(arr[i], false));//深度拷贝每个元素
}
return newArray;
}
//对对象深度拷贝
private function copyOverObject(objToCopy:Object, registerAlias:Boolean = false):Object
{
if(registerAlias) {
var className:String = flash.utils.getQualifiedClassName(objToCopy);
flash.net.registerClassAlias(className,(flash.utils.getDefinitionByName(className) as Class));
}
return mx.utils.ObjectUtil.copy(objToCopy);
}
]]>
</mx:Script>
</mx:Application>