as3:如何按值复制对象

我需要在每个其他对象中都有一个共同对象的实例。我正在对每个子对象中的对象值进行修改。 例如。我有一张瓷砖地图,一个机器人按特定顺序移动它们。每个机器人都标记着已经被他访问过的瓷砖,因为访问=真。但总的来说我不希望改变主地图...... 我试图建立一个例子:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" 
    applicationComplete="complete()">
    <mx:Script>
        <![CDATA[
            private var array:Array = new Array( 1, 2, 3, 4);
            public function complete():void
            {
                trace("here " + array);
                var a:Array = array;
                a[0] = 100;
                trace("here " + array);
            }
        ]]>
    </mx:Script>
</mx:Application>
有人可以帮我理解如何通过值(不是通过引用)复制数组,例如数组     
已邀请:
function clone ( arr:Array ):Array
{
    return arr.map( function( item:*, ..r ):*
        {
            return item;
        } );
}
编辑: 可能包含一些语法错误......
public class MyObject
{
    private var arr:Array;
    private var bool:Boolean;

    // ...

    public function clone ():MyObject
    {
        var obj:MyObject = new MyObject();

        // clone values
        obj.arr = this.arr.slice();
        obj.bool = this.bool;

        return obj;
    }
}
    
对于克隆数组,您可以使用Array.slice。
var arrCopy:Array = arrOrig.slice();
    
这是poke描述的方法的替代方法: 我首先想对poke的帖子提出一些观点。 “为该特定对象定义自己的克隆函数。没有任何特殊函数可以自动为任意对象执行此操作。”假。 ActionScript具有内置的序列化方法,称为AMF(ActionScript消息格式)。 AMF可用于执行非基本对象的副本。 “使用自定义克隆方法有很大的优势,你可以准确地决定将要复制什么,以及如何复制它......”这正是你序列化一个对象时所做的,所以没有什么大的优点您的自定义克隆方法比序列化方法。 “......并且返回类型是正确的(即你不需要施放)。”您也不需要强制转换序列化对象。但序列化具有通用的附加好处,使得复制动态的功能,而不仅限于特定类型。 “[实现一个接口](鉴于clone返回一个特殊类型的对象,这将是非常不合适的)”必须定义一个返回类型会使进程静态,从而锁定您使用特定类型。如果我们使用该语言的动态属性,我们可以创建一个通用克隆方法而不关心类型。对此没什么不妥。 “如果你对序列化对象进行两次反序列化,你会得到一个对象的副本,这只是序列化的另一个影响。”通过调用slice()或concat()而不使用任何参数获得数组副本的事实只是这些方法的副作用。我真的没有在这里看到你的观点。此外,序列化的核心是复制。序列化然后反序列化的行为是制作副本的行为。你不会以某种方式获得完全相同的内存,引用和所有完整。 我有一个问题:你如何在克隆方法中处理嵌套的非原始类型? 在你的问题中,你说“有人可以帮助我理解我如何复制例如数组,按值,而不是通过引用”我认为,在复制对象时,了解浅拷贝和深拷贝之间的区别很重要。 浅拷贝 这里提供的解决方案(Array.slice()和Array.concat())称为浅拷贝。你得到的是数组的副本。如果数组的内容是基本类型(通过值而不是通过引用传递的那些),那么您有两个唯一对象,原始对象和副本。但是,如果您的数组包含通过引用传递的对象,则数组的原始数据和副本将具有完全相同的内容。如果对原始数组中的对象进行更改,则更改将反映在复制的数组中。虽然这有时可能是你想要的,但并非总是如此。 深拷贝 深层副本将遍历您要复制的对象的层次结构,并复制它找到的任何对象。然后,您将被允许对复制的对象进行任何更改,而不会在原始对象中反映任何更改。 如果要按照poke建议定义自定义克隆方法,则复制非原始类型会变得过于复杂。您必须遍历对象的属性并在任何非基本类型上调用自定义clone()方法。但是,如果遇到像Array或Dictionary这样的内置非基本类型,那么你必须重新创建对象,遍历其内容,然后通过检查它是否是非原始的来重新开始,调用它的clone()方法,如果它有一个,或处理数组和字典。它变得过于复杂。总而言之,这个方法有两个问题:你必须自己处理Arrays和Dictionaries(以及任何内置的非原始类型);您必须在嵌套对象上专门调用clone方法(并且知道它们已定义了clone方法)。 另一种方法是使用AMF序列化然后反序列化对象,为您提供深层复制。这对于Arrays,Dictionaries以及依赖于公共属性的任何非原语都是开箱即用的。
var t:Array = [];
t[0] = [1, 2, 3];
t[1] = new Dictionary();
t[1]['hello'] = 'world';
t[2] = {'my': 'object'}
trace(t, t[1]['hello'], t[2]['my']); // [trace] 1,2,3,[object Dictionary],[object Object] world object
var t2:Array = clone(t);
trace(t2, t2[1]['hello'], t2[2]['my']); // [trace] 1,2,3,[object Dictionary],[object Object] world object
t[0] = [4, 5, 6];
t[1]['hello'] = 'earth';
t[2]['my'] = 'other object';
trace('modified values');  // [trace] modified values
trace(t, t[1]['hello'], t[2]['my']);  // [trace] 4,5,6,[object Dictionary],[object Object] earth other object
trace(t2, t2[1]['hello'], t2[2]['my']);  // [trace] 1,2,3,[object Dictionary],[object Object] world object

function clone(source:*):* {
    var b:ByteArray = new ByteArray();
    b.writeObject(source);
    b.position = 0;
    return(b.readObject());
}
这涵盖了自定义克隆方法的第一个问题,以及上面的第一个问题。如您所见,所有对象及其内容都是使用内置方法复制的。 我在这里展示了如何创建克隆方法的实现,但是你可以在:mx.utils.ObjectUtil中找到一个。 如果要深度复制一个私有存储其数据的对象,则必须实现IExternalizable接口。这将迫使您实现两种方法:
public function writeExternal(output:IDataOutput):void
public function readExternal(input:IDataInput):void
在这些函数中,您将私有变量写入输出对象,然后从输入到私有变量读取它们。然后,当您调用clone时,您将获得对象的完整副本。请记住对所有嵌套对象执行此操作。 这是一个包含两个类的简单实现示例:
package {

    import flash.utils.IExternalizable;
    import flash.utils.IDataInput;
    import flash.utils.IDataOutput;
    import flash.net.registerClassAlias;

    public class Car implements IExternalizable {

    private var type:String;
        private var contents:Array;

        public function Car() {
            registerClassAlias("Car", Car);
        }

    public function setVars(type:String, contents:Array):void {
            this.type = type;
            this.contents = contents;
        }

    public function setType(type:String):void {
            this.type = type;
        }


        public function writeExternal(output:IDataOutput):void {
            output.writeUTF(type);
            output.writeObject(contents);
        }

    public function readExternal(input:IDataInput):void {
            type = input.readUTF();
            contents = input.readObject();
    }

        public function toString():String {
            return "[Car type = " + type + ", contents = " + contents + "]";
    }

    }

}
和:
package {

    import flash.utils.IExternalizable;
    import flash.utils.IDataInput;
    import flash.utils.IDataOutput;
    import flash.net.registerClassAlias;

    public class Person implements IExternalizable {

    private var firstName:String;
        private var secondName:String;

        public function Person() {
            registerClassAlias("Person", Person);
        }

    public function setVars(firstName:String, secondName:String):void {
            this.firstName = firstName;
            this.secondName = secondName;
        }

        public function writeExternal(output:IDataOutput):void {
            output.writeUTF(firstName);
            output.writeUTF(secondName);
        }

    public function readExternal(input:IDataInput):void {
            firstName = input.readUTF();
            secondName = input.readUTF();
        }

        public function toString():String {
            return "[Person firstName = " + firstName + ", secondName = " + secondName + "]";
        }

    }

}
测试它们:
package {

    import flash.display.Sprite;
    import flash.utils.ByteArray;
    import flash.utils.Dictionary;

    public class Serial extends Sprite {

    public function Serial() {

            var person0:Person = new Person();
            person0.setVars("John", "Doe");
            var person1:Person = new Person();
            person1.setVars("Jane", "Doe");
            var car0:Car = new Car();
            car0.setVars("Ford", [person0, person1]);

            var person2:Person = new Person();
            person2.setVars("Joe", "Bloggs");
            var car1:Car = new Car();
            car1.setVars("Vauxhall", [person2]);

            var street:Array = [car0, car1];
            trace("street = " + street); // [trace] street = [Car type = Ford, contents = [Person firstName = John, secondName = Doe],[Person firstName = Jane, secondName = Doe]],[Car type = Vauxhall, contents = [Person firstName = Joe, secondName = Bloggs]]

            var street2:Array = clone(street);
            trace("street2 = " + street2); // [trace] street2 = [Car type = Ford, contents = [Person firstName = John, secondName = Doe],[Person firstName = Jane, secondName = Doe]],[Car type = Vauxhall, contents = [Person firstName = Joe, secondName = Bloggs]]

            person0.setVars("Max", "Headroom");
            person1.setVars("Simon", "Le Bon");
            car0.setType("Mini");

            person2.setVars("Harry", "Wotsit");
            car1.setType("Austin");

        trace("modified values of street"); // [trace] modified values of street
            trace("street = " + street); // [trace] street = [Car type = Mini, contents = [Person firstName = Max, secondName = Headroom],[Person firstName = Simon, secondName = Le Bon]],[Car type = Austin, contents = [Person firstName = Harry, secondName = Wotsit]]
            trace("street2 = " + street2); // [trace] street2 = [Car type = Ford, contents = [Person firstName = John, secondName = Doe],[Person firstName = Jane, secondName = Doe]],[Car type = Vauxhall, contents = [Person firstName = Joe, secondName = Bloggs]]

        }

        private function clone(source:*):* {
            var b:ByteArray = new ByteArray();
            b.writeObject(source);
            b.position = 0;
            return(b.readObject());
    }

    }

}
这涵盖了自定义克隆方法的第二个问题。正如您所看到的,我们不必担心调用任何克隆方法,这一切都得到了我们的关注。 我并不是说它并非完全没有缺点,但它确实为深度复制对象提供了一些功能。 一些缺点包括: 您不能在构造函数中包含任何必需的参数。 它不存储引用数据,因此如果两个对象包含相同的引用,则将返回两个不同的对象。 克隆方法放在哪里。我认为它真的属于Object,可能就原型而言。这样可以使每个对象都可以复制,如果您愿意,可以准确指定对象的复制方式。 请参阅Adobe关于复制阵列的观点:http://livedocs.adobe.com/flex/3/html/help.html?content = 10_Lists_of_data_6.html 另请注意,Adobe从Java中窃取了这种技术。     

要回复问题请先登录注册