There are 2 contexts where weak reference is used. The first is Dictionary with weak references on object keys, and the second is adding event listeners using weak references. The reason you must be careful when using event listeners is that the EventDispatcher class doesn't have a method to just remove all event listeners that it has added before, hence you have to manually remove each event listener you've added. Imagine you use strong reference on event listeners and later forget to remove them from the event dispatcher, the event listeners will continue to exist as long as the event dispatcher exist, possibly leading to memory leak. Having said that, it's a good practice to always remove important event listeners manually, especially if the fact that they receive events or not will affect the logic flow of your program.

By default, addEventListener function add strong referenced event listener. To use weak reference, simply pass the parameter useWeakReference as true like this:

addEventListener(someEvent, eventHandler, false, 0, true);


The advantage of using weak reference on event listeners is the event listeners and the objects that they are members of are now subject to garbage collection, thereby preventing memory leak. Note that class-level member functions are not subject to garbage collection.
The disadvantage is your code will be more verbose. Some developers go as far as recommending to always pass useWeakReference. I don't feel this necessary, for example, handlers function of UI components such as buttons or text fields will most likely reside within the same class that linked to the display container of those UI components, they are self contained in one class so there is no risk of memory leak, Flash GC will be able to clean them using mark sweeping strategy. (If you don't know what mark sweeping is, please refer to Grant's article that I mentioned at the beginning)

Now let's have a look at the setup for testing event listeners. First, there are 3 classes whose functions will be used as event listeners. ClassA extends MovieClip and it links to a symbol named ClassA in the .fla file.

public class ClassA extends MovieClip
{
    public function ClassA()
    {
    }
 
    public function customHandler(e:Event):void
    {
        trace("Class A custom Handler " + getTimer());
    }
}


ClassB and ClassC are the same.
public class ClassB
{
    public function ClassB()
    {
    }
   
    public function customHandler(e:Event):void
    {
        trace("Class B custom Handler " + getTimer());
    }
}


public class ClassC
{
    public function ClassC()
    {
    }
 
    public function customHandler(e:Event):void
    {
        trace("Class C custom Handler " + getTimer());
    }
}


Why we are testing a movie clip will be cleared shortly.
Code in frame 4:

this['mDisposableObjectA'] = new ClassA();
this['mDisposableObjectB'] = new ClassB();
this['mDisposableObjectC'] = new ClassC();

addEventListener(Event.ENTER_FRAME,
    this['mDisposableObjectA'].customHandler,
    false,
    0,
    true);

addEventListener(Event.ENTER_FRAME,
                 this['mDisposableObjectB'].customHandler);

addEventListener(Event.ENTER_FRAME,
    this['mDisposableObjectC'].customHandler,
    false,
    0,
    true);

btnRemove.addEventListener(MouseEvent.CLICK, removeClickHandler);

function removeClickHandler(e:Event):void
{
    this['mDisposableObjectA'] = null;
    this['mDisposableObjectB'] = null;
    this['mDisposableObjectC'] = null;
}



As can be seen, 3 instances of ClassA, ClassB and ClassC are created. Then their functions customHandler are added as event listener of Event.ENTER_FRAME of the stage. From now on, they will print out a message every frame:

...
Class B custom Handler 4644
Class C custom Handler 4644
Class A custom Handler 4732
Class B custom Handler 4732
Class C custom Handler 4732
Class A custom Handler 4820
Class B custom Handler 4820
Class C custom Handler 4820
Class A custom Handler 4908
Class B custom Handler 4908
Class C custom Handler 4908
...


If we see the trace output of an instance, naturally it means that the instance still persists in memory, otherwise it has been garbage collected. It is designed that if you click on the button "Remove Reference", it will attempt to remove all 3 objects by setting them to null. Note that ClassA and ClassC instances were added as weak references but ClassB instance were added as strong reference. So it is expected that only ClassA and ClassC instances will be garbage collected. Run the .fla file, click on "Test Event Listener", then click "Remove Reference" and see for yourself. Well, a little unexpected, or as expected, outcome, something like this:

...
Class B custom Handler 341377
Class A custom Handler 341459
Class B custom Handler 341459
Class A custom Handler 341621
Class B custom Handler 341621
Class A custom Handler 341709
Class B custom Handler 341709
Class A custom Handler 341880
Class B custom Handler 341880
Class A custom Handler 341965
Class B custom Handler 341965
Class A custom Handler 342130
Class B custom Handler 342130
Class A custom Handler 342219
Class B custom Handler 342219
...


So even though that ClassC instance has been garbage collected, ClassA instance persists. The reason is it's up to the garbage collector to decide when to collect unused objects. In this case, collecting objects such as MovieClip takes mark sweeping strategy since movie clips normally contains children, which in turn hold reference to their parent, in other words, circular reference. Mark sweeping is expensive, therefore, it doesn't get called casually but when Flash uses too much memory and it decides it's time to clean up. In fact, you can try leaving our test running for a very long time and ClassA instance still persists.

To prove that Flash doesn't want to remove ClassA instance and not that it cannot, let's move on to the next test on Frame 5.

this['mDisposableObjectA'] = new ClassA();
this['mDisposableObjectB'] = new ClassB();
this['mDisposableObjectC'] = new ClassC();

addEventListener(Event.ENTER_FRAME,
     this['mDisposableObjectA'].customHandler,
     false,
     0,
     true);

addEventListener(Event.ENTER_FRAME,
     this['mDisposableObjectB'].customHandler);

addEventListener(Event.ENTER_FRAME,
     this['mDisposableObjectC'].customHandler,
     false,
     0,
     true);

btnRemove.addEventListener(MouseEvent.CLICK, removeClickHandler);

var strongDict1:Dictionary = new Dictionary();

addEventListener(Event.ENTER_FRAME, enterFrameStrongDic1);

function enterFrameStrongDic1(aEvent:Event):void
{
 var anArray:Array = new Array(10000);
 for (var i:int = 0; i < anArray.length; i++) {
  anArray[i] = 0;
 }
 strongDict1[anArray] = 1;
 var n:int = 0;
 for (var key:* in strongDict1) {
  n++;
 }
}



This frame is basically the same as Frame 4, however, an array of 10,000 integers is constantly added to memory. This is kind of an incentive to encourage GC to recycle unused memory space. Run it by first choose "Test Event Listener Final" then "Remove Reference". The output:

....
Class A custom Handler 9935
Class B custom Handler 9935
Class C custom Handler 9935
Class A custom Handler 10027
Class B custom Handler 10027
Class C custom Handler 10027
Class A custom Handler 10111
Class B custom Handler 10111
Class C custom Handler 10111
Class A custom Handler 10194
Class B custom Handler 10194
Class C custom Handler 10194
Class A custom Handler 10281
Class B custom Handler 10281
Class A custom Handler 10367
Class B custom Handler 10367
Class A custom Handler 10455
Class B custom Handler 10455
Class A custom Handler 10543
Class B custom Handler 10544
Class A custom Handler 10631
Class B custom Handler 10632
Class A custom Handler 10719
Class B custom Handler 10719
Class A custom Handler 10811
Class B custom Handler 10811
Class A custom Handler 10895
Class B custom Handler 10895
Class A custom Handler 10983
Class B custom Handler 10983
Class A custom Handler 11071
Class B custom Handler 11071
Class A custom Handler 11159
Class B custom Handler 11159
Class A custom Handler 11247
Class B custom Handler 11247
Class A custom Handler 11336
Class B custom Handler 11336
Class A custom Handler 11423
Class B custom Handler 11423
Class A custom Handler 11511
Class B custom Handler 11511
Class A custom Handler 11599
Class B custom Handler 11599
Class A custom Handler 11687
Class B custom Handler 11687
Class A custom Handler 11779
Class B custom Handler 11779
Class A custom Handler 11863
Class B custom Handler 11863
Class A custom Handler 11951
Class B custom Handler 11951
Class B custom Handler 12035
Class B custom Handler 12119
Class B custom Handler 12207
...


As you can see, as soon as attempt to remove ClassA and ClassC instances were executed, ClassC instance were immediately removed, but ClassA instance stays for several frames before finally removed. This late removal occurs a lot in real programs so there's no need to worry if memory usage does not drop immedialy after you remove some movie clips. A neat hack that is commonly used is to create a local connection and connect it to a non-existent connection. Please refrain from using this hack too frequently for garbage collection is always expensive.

try {
    new LocalConnection.connect('foo');
    new LocalConnection.connect('foo');
} catch (e:*) {}