ADM Blog No matter how you see things, reality changes when you reach understanding

5Jun/0918

How to clone (duplicate) an object in ActionScript 3

For a project I needed to clone an object of unknown type. And by clone I mean to create a new instance of that same type and then fill out all its properties (including getters and setters) to mirror the original object.

Thanks to a friend, I discovered the describeType function in AS3. But this alone will only take care of the copying part. To create an object of the same type as another one we use getDefinitionByName.

Although Flash reflection is pretty basic, with a little work it will do the trick.

Get the application files.

Here's the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
< ?xml version="1.0" encoding="utf-8"?>
<mx :Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:local="*" creationComplete="init()">
</mx><mx :Script>
 < ![CDATA[
 
     import mx.controls.Alert;
 
     private var source:DataObject = new DataObject();
     private var cloneObject:DataObject;
 
 
     private function init():void {
 
         source.name = 'John Doe';
         source.howMany = 4.5;
         source.when = new Date(0);
         source.complexProp = new DataObject();
         source.complexProp.name = 'Name in sub-object';
 
         cloneObject = UtilFunctions.clone(source) as DataObject;
 
         Alert.show("Clone:\nname = " + cloneObject.name + "\nhowMany = " + cloneObject.howMany + "\nwhen = " + cloneObject.when + "\ncomplexProp.name = " + cloneObject.complexProp.name);
     }
 
     /**
 
      * describeType will produce this (for a DataObject instance):
      *
      * <type name="DataObject" base="Object" isDynamic="false" isFinal="false" isStatic="false">
 
           <extendsclass type="Object"/>
           <accessor name="isHandicap" access="writeonly" type="Boolean" declaredBy="DataObject"/>
 
           <variable name="howMany" type="Number"/>
           <accessor name="complexProp" access="readwrite" type="DataObject" declaredBy="DataObject"/>
 
           <variable name="name" type="String"/>
           <variable name="when" type="Date"/>
 
 
      *
      * */
 
 ]]>
 
</mx>

And the UtilFunctions.as file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package
{
 import flash.utils.describeType;
 import flash.utils.getDefinitionByName;
 import flash.utils.getQualifiedClassName;
 
 public class UtilFunctions
 {
 
 
     public static function newSibling(sourceObj:Object):* {
         if(sourceObj) {
 
             var objSibling:*;
             try {
                 var classOfSourceObj:Class = getDefinitionByName(getQualifiedClassName(sourceObj)) as Class;
                 objSibling = new classOfSourceObj();
             }
 
             catch(e:Object) {}
 
             return objSibling;
         }
         return null;
     }
 
     public static function clone(source:Object):Object {
 
         var clone:Object;
         if(source) {
             clone = newSibling(source);
 
             if(clone) {
                 copyData(source, clone);
             }
         }
 
         return clone;
     }
 
     public static function copyData(source:Object, destination:Object):void {
 
         //copies data from commonly named properties and getter/setter pairs
         if((source) && (destination)) {
 
             try {
                 var sourceInfo:XML = describeType(source);
                 var prop:XML;
 
                 for each(prop in sourceInfo.variable) {
 
                     if(destination.hasOwnProperty(prop.@name)) {
                         destination[prop.@name] = source[prop.@name];
                     }
 
                 }
 
                 for each(prop in sourceInfo.accessor) {
                     if(prop.@access == "readwrite") {
                         if(destination.hasOwnProperty(prop.@name)) {
                             destination[prop.@name] = source[prop.@name];
                         }
 
                     }
                 }
             }
             catch (err:Object) {
                 ;
             }
         }
     }
 }
}

by Evolvernie

Related posts:

  1. Serialize JavaScript object to JSON
  2. How to identify at runtime if the swf is in debug or release mode/build
  3. Neural networks in ActionScript 3
  4. Create professional Flex components
  5. Ho-To: Install Alchemy
Comments (18) Trackbacks (2)
  1. Evolvernie this is fantastic! I was having some really weird results using ByteArray.readObject()when trying to clone some objects and these classes have turned out to be an absolute life saver.

  2. Thanks a lot. I use it to set the proxyImage for DragManager.
    It’s perfect!

    BTW, which license does it apply? Can I use it freely?

  3. @CHEN Cheng
    yes, you can use it however you want.

  4. Whaou!!!! très très bon!!! Merci à toi! ça va me servir!
    thanks a lot!!!

  5. Thanks. Works fine.

  6. really great, thx a lot!!

  7. nice work. doesnt seem to work with Sound objects?

  8. Thank You for this, works with loaded bitmap

  9. Thx, works great and much appreciated!

  10. Nice! Your solution made fixing a showstopping problem on our project a no-brainer. Thank you!

  11. Awesome!! Just exactly what I was looking for.. thanks a ton

  12. I noticed that this will only work for Objects with optional or no arguments passed in the constructor. Also private properties with no setters will cause errors

  13. Compliments.

    A problem: methods are not cloned =\

  14. This is a great class.

    Sadly it does not work with sound objects

  15. This doesn’t work for MovieClip objects.


Leave a comment


Uses wordpress plugins developed by www.wpdevelop.com