There have been plenty of times in projects where I've wanted to compare two objects to see if they are equal. I don't really care if they are the same object, all I care about is if they are identical - meaning that they could be two unique objects, but that the values of their properties are equal to each other.


Typically, when comparing two values in AS, you'll write something like this:

  1. if (mario == luigi) {
  2.         // do something useful here...
  3. }

Which is all well and good if the values being compared are primitives such as Numbers, ints, uints, Strings, etc., because this compares the values of these types of objects. However, things start to get a little tricky when you want to compare something more complex like Arrays or more advanced Objects.

  1. var array1:Array = [1, 2, 3];
  2. var array2:Array = [1, 2, 3];
  3.  
  4. if (array1 == array2) {
  5.         // do something useful here...
  6. }

Using the example above will compare the objects, but it will compare the references not the values of the two arrays. Basically, it'll check to see if array1 is pointing to the same Array as array2. It will not check to see if the values contained in the Array match. The same goes for objects like Points, Rectangles, MyCustomObject, etc.

So how do we get around this?

The equals() Method

Many developers will get around this by building a custom equals method into their objects. This method will then know how to compare objects of that type, so any code using that object doesn't need to know anything about it. Take a look at the Rectangle.equals() method. Instead of you needing to manually compare the x, y, width, and height values of the Rectangle, you can simply say:

  1. if (rect1.equals(rect2) {...

and the Rectangle class will take over, comparing the object's properties for you. Works great, as long as the classes you're using provide and equals() (or similar) method you can use.

Use mx.utils.ObjectUtil.compare()

mx.utils.ObjectUtil is a static class that is part of the Flex framework. It allows you to supply two objects, as well as a depth of how deeply to compare the two objects. This method will recursively compare the properties of the supplied objects and let you know if they are equal. It works pretty good.

Use ByteArray

Lastly, I'll mention is something I was playing with the other day, and so far, seems to be working pretty good. I wrote a class with a method that allows you to compare two objects by first writing the objects to a ByteArray, which then serializes the objects. Once the objects have been serialized, bits are then compared:

  1. package {
  2.         import flash.utils.ByteArray;
  3.        
  4.         public class ObjectTools {
  5.                
  6.                 public function ObjectTools () {
  7.                        
  8.                 }
  9.                
  10.                
  11.                 /**
  12.                  * Compares two objects and checks if they are identical. Does not compare the objects by reference,
  13.                  * but compares to see if the values of the properties are identical.
  14.                  * 
  15.                  * @param obj1
  16.                  * @param obj2
  17.                  *
  18.                  * @return
  19.                  */          
  20.                 public static function compare (obj1:Object, obj2:Object):Boolean {
  21.                        
  22.                         var b1:ByteArray = new ByteArray();
  23.                         var b2:ByteArray = new ByteArray();
  24.                        
  25.                         b1.writeObject(obj1);
  26.                         b2.writeObject(obj2);
  27.                        
  28.                         // compare the lengths first
  29.                         var size:uint = b1.length;
  30.                         if (b1.length == b2.length) {
  31.                                 b1.position = 0;
  32.                                 b2.position = 0;
  33.                                
  34.                                 // then the bits
  35.                                 while (b1.position < size) {
  36.                                         var v1:int = b1.readByte();
  37.                                         if (v1 != b2.readByte()) {
  38.                                                 return false;
  39.                                         }
  40.                                 }                            
  41.                         }
  42.                        
  43.                        
  44.                         if (b1.toString() == b2.toString()) {
  45.                                 return true;
  46.                         }              
  47.                        
  48.                         return false;
  49.                 }
  50.         }
  51. }

You can then use this class like so:

  1. package {
  2.         import flash.display.Sprite;
  3.        
  4.         import ObjectTools;
  5.         import flash.geom.Rectangle;
  6.         import flash.display.BitmapData;
  7.  
  8.         public class CompareObjects extends Sprite
  9.         {
  10.                 public function CompareObjects()
  11.                 {
  12.                         // basic objects
  13.                         var obj1:Object = {foo:1, bar:2};
  14.                         var obj2:Object = {foo:1, bar:2};                     
  15.                         trace ("Simple Objects:", ObjectTools.compare(obj1, obj2)); // outputs true
  16.                         trace ("Boolean:", (obj1 == obj2)); // false
  17.                        
  18.                         // Arrays
  19.                         var array1:Array = [2, "cheese", [1, 2, 3]];
  20.                         var array2:Array = [2, "cheese", [1, 2, 3]];
  21.                         var array3:Array = [2, "cheese", false];
  22.                         trace ("Arrays:", ObjectTools.compare(array1, array2)); // outputs true
  23.                         trace ("Arrays 2:", ObjectTools.compare(array1, array3)); // outputs false
  24.                        
  25.                         // More Complex Objects
  26.                         var rect1:Rectangle = new Rectangle (0, 0, 100, 100);
  27.                         var rect2:Rectangle = new Rectangle (0, 0, 100, 100);
  28.                         trace ("Rectangles:", ObjectTools.compare(rect1, rect2)); // outputs true                     
  29.                 }
  30.         }
  31. }

This method isn't perfect, and doesn't work for everything. For example, it won't compare two BitmapData objects and let you know if one is a red triangle, and the other a blue circle, but for 99% of the times I've needed to compare objects like I've been talking about, it seems to work pretty good.