AS3, clarification on the 'this' pointer - actionscript-3

I am writing a program in flex, and I am having an issue with the this pointer.
I have a function call inside of a function and I am wondering which event my this pointer is passing.
private function funcA(someArgument)
{
newDialog.show("Title", "Body", funcB, this) // the 'this' is the argument for funcB
}
private function funcB(CloseEvent:event)
{
if(event == Event.CANCEL)
doStuff;
if(event == Event.COMPLETE)
doOtherStuff;
}
To clarify, my question is, when I pass the this pointer into the function in the newDialog, am I passing my newly created Dialogue or am I passing in funcA. I'm thinking and hoping its the former.
I would just test this manually but the system is really large and currently tied in with other events so its difficult for me to just instantiate objects to test them.

While null is correct, the method signature on funcB looks like it should be added as an event listener. funcB is expecting an event. All events have a property target, which is the actual object that dispatched the event, and currentTarget, which is the object that was being listened to. These will only be different in the case of bubbling events on the display list, where a child object really dispatched the event.
If the Class you found this code in is not a subclass of Event, I would expect funcB to error pretty hard. If it is a subclass of Event, it shouldn't be, because the functionality in funcA is nothing that should ever be the responsibility of an event.

when I pass the this pointer into the function in the newDialog, am I passing my newly created Dialogue or am I passing in funcA.
Neither one.
You have a private function, which is a member of a class. In order to call that function, an object has to be created that's an instance of that class and then funcA can be called on that object.
this is a reference to exactly that object.

Related

How to pass object, MouseEvent.CLICK and function to trigger

I want to pass to function object, const of type MouseEvent.CLICK and function to trigger. In my case:
my class Assistant:
public static function addEventListenerTo(obj:Object, MouseEventConst:String, functinToTrigger:Function) {
obj.addEventListener(MouseEventConst, functinToTrigger:Function);
}
and my class Engine which invokes
Assistant.addEventListenerTo(deck,"MouseEvent.CLICK",showObject);
Please give me advice how to make it work. Thanks.
In the code you provide there is one compiler error (the one Tahir Ahmed pointed to in his second comment).
Fixing this by removing the second :Function in the first code block:
public static function addEventListenerTo
(obj:Object, MouseEventConst:String, functinToTrigger:Function)
{
obj.addEventListener(MouseEventConst, functinToTrigger);
}
will let the code compile. (I wrapped the Method signature to avoid the scrollbar, this is not required to make it compile.)
The other major problem is a configuration error (or maybe a typo): the one about MouseEvent.CLICK. (the one Tahir Ahmed pointed to in his first comment)
Looking at the documentation it is defined to have the value "click" (a String literal following the AS3 convention of the lowercase constant name). So to pass it to your method you can either put in a reference to the constant by writing MouseEvent.CLICK (without the "s around it) or reach the same goal with passing its value by writing "click".
As using the reference will prevent mistyping because the compiler checks it, the first approach should be preferred.
So calling the Method should look like this:
Assistant.addEventListenerTo(deck, MouseEvent.CLICK, showObject);
If you want to know why your version didn't work you should read a simple introduction to AS3 Events and EventDispatchers. As a short hint: if deck would dispatch an Event that has its type property set to "MouseEvent.CLICK" your listener would get fired.
While you are at it, you could improve the quality of your code by to major things:
the first one is about avoiding getting runtime Errors and prefering compile time errors: Not every instance of type Object has a method called addEventListener. In your current code, when you pass an instance to Assistant.addEventListenerTo as first parameter, that doesn't have this method (e.g. {} or an instance of type Array), the error will get thrown while your swf is displayed and it might stop displaying anything and might show an error message to the user.
If the type of the parameter is IEventDispatcher instead, the compiler will already tell you that you passed an incompatible instance.
The second one is about names and conventions, which helps other developers to read your code (an having more fun helping you).
what you called MouseEventConst is called an event type in AS3, which provides a better name for a parameter, as it being a String nobody stops anybody from passing contants of other event types like Event
the functionToTrigger is what is called a listener (or event listener)
the first letter of parameter names should be lower case
So if I would have written the static method it would look like this:
import flash.events.*;
public class Assistent{
public static function addEventListenerTo
(dispatcher:IEventDispatcher, eventType:String, listener:Function)
{
dispatcher.addEventListener(eventType, listener);
}
}

Set event.target to null

I want to nullify the event.target for garbage collection as the moveclip is no longer needed. What I have roughly is this:
mc.addEventListener(MouseEvent.CLICK, destroy);
public function destroy(event:MouseEvent):void {
event.target.parent.removeChild(event.target);
event.target.removeEventListener(MouseEvent.CLICK, destroyShape);
event.target = null; //THIS IS WHAT I WANT TO ACHIEVE
}
I'm sure this is relatively simple but I'm not sure how to do it.
thanks
You can't change MouseEvent.target value. It's a read only property. If your MovieClip doesn't exist (removeChild) and you removed event handler
mc.removeEventListener(MouseEvent.CLICK, destroy);
then the garbage collector automatically will remove it.
What you are trying to achieve (if it was even possible) would achieve nothing in term of Garbage Collection.
Unless redispatched the event will be garbage collected as soon as the method is done running. All properties of the event will also be discarded. This garbage collection of the event itself and its properties will have absolutely NO EFFECT on the object they point to in term of Garbage collection.
In the scope at which the event was dispatched in the first place the object will continue to exist after the event itself has been discarded. That is at that scope that the object reference must be nullified, not at the event listener scope where it will have no effect since the object still exists at the dispatching scope.
The solution accepted also does nothing. It is as relevant as applying a bandage to a wooden leg. Any local variable in function/method qualify for GC immediately after the method runs. Nullifying those variables has no effect whatsoever and does not constitute a valid answer to any problem and certainly not a GC problem. That those variables are GC does also not constitute a guaranty that the object they point to will be GC.
This is a case where a question about an inexistent and misunderstood problem is asked and answered by posting a false and irrelevant solution.
Case in point: Only a DisplayObject currently in a display list and attached to the stage has the ability to be the target of a MouseEvent. It is simply impossible for that object to become available for garbage collection before it is removed from the display list it belongs to. For those reasons that object cannot qualify for GC at the time the MouseEvent listener runs since that object still has at least one strong reference because it is attached to a display list. This is the proof that what the PO asks is misguided and any code examples are misguided as well since they cannot qualify the object for GC at that point in time.
As #subdan states, the target property of any Event is a readonly property.
You can still null your movie clip but not like in your sample.
mc.addEventListener(MouseEvent.CLICK, destroy);
public function destroy(event:MouseEvent):void
{
var myMC:MovieClip = event.target as MovieClip;
if( myMC )
{
myMC.removeEventListener(MouseEvent.CLICK, destroyShape);
myMC.parent.removeChild(myMC);
myMC = null; //THIS IS WHAT I WANT TO ACHIEVE
}
}

Want to clear some doubts regarding Garbage Collection ( AS3.0)

package
{
public class SomeClass
{
public var myBtn:Button ;
public function SomeClass()
{
myBtn.addEventListener( MouseEvent.CLICK, clickFunction) ;
}
function clickFunction(e:Event){
}
}
}
Main Class:
var someClass:SomeClass = new SomeClass(); // step 1
addChild(someClass); // step 2
removeChild(someClass); // step 3
someClass = null // step 4
In the above, I want to completely destroy the someClass instance, so in step 4 it's been assigned null value.
Q1) Is step 4 ( assignment to null ) right way to destroy the instances ?
Q2) I referred : http://gskinner.com/blog/archives/2006/06/as3_resource_ma.html using delete keyword for objects. But i don't think delete keyword can be used for class instances ? How to use it in this case then ?
Q3) What happens to myBtn eventListener in SomeClass. Should i add a removeEventListener manually, before destroying instances of SomeClass. Or would it get destroyed automatically ?
Thanks
1/ Yes. (I assume the someClass variable is an instance variable)
2/ delete does not only remove the value of a variable, but even the variable definition. Since classes in AS3 are sealed in general, it won't work. I.e. delete should only be used on dynamically created members. Mainly "keys" of Object or Dictionary instances. But obviously you can remove the member definition of any class marked as dynamic using delete.
3/ Yes, always remove event listeners manually. You can create weakly referenced event listeners when registering the handler as a listener, but it's best to always make sure event listeners are removed manually, it's more readable, clear and fail-safe.
I tend to have a destroy method in all my classes, which can be called by the instance owner when it's cleaning up its references to a certain instance. This destroy method will unregister all event listeners, nullify instance members and do all kinds of cleanup.
The SomeClass instance you created will get garbage-collected after there are no longer any references to it. By setting your variable to null, it removes that reference, and the SomeClass instance will get garbage-collected as long as there are no more references to it.
In the code above, you do not need to remove the event listener. When a SomeClass instance is collected, all of its member variables will be collected (unless they're referenced elsewhere). Because the event listener has been added to the button, it will be collected when the button is collected.
Something to note, however: if instead of myBtn.addEventListener you had used stage.addEventListener, the stage would retain a reference to your callback function and you could end up with a memory leak. Always remove event listeners that are assigned to objects that will still be around after you care about the listener.
Creynder's advice is good: remove event listeners as a matter of habit. It's only really necessary, however, when an event listener's dispatcher is going to hang around but you don't want the callback to stay in memory.

Actionscript 3.0: What does the parameter 'e' do in e:KeyboardEvent

Ive been using the 'event' parameter for my KeyboardEvents and MouseEvents in a recent project ive been working on for my course (VERY BASIC).
Im not entirely sure on what the 'e' part of e:KeyboardEvent actually does, and ive been asked to find out what information the parameter 'e' can actually access when using it.
Im sorry if the questions badly written, its been a long night!
EDIT: If A method takes the parameter (e:KeyboardEvent). what information could we access through the use of the parameter e?
e represents an instance of KeyboardEvent (the instance being passed to your listening function).
The most important property of KeyboardEvent (referenced by e in your example) is keyCode.
This determines which key is being pressed/released.
eg:
stage.addEventListener(KeyboardEvent.KEY_DOWN, _keyDown);
function _keyDown(e:KeyboardEvent):void
{
trace(e.keyCode); // Will be 65 if you press 'a'.
}
I'm assuming you have some function like this
function someFunction(e:KeyboardEvent):void
{
// code
}
You can access any information from the KeyboardEvent class, just the same as if the parameter were called "event". The name of the parameter doesn't affect what you can access through it; the type does.
Edit: "e" is just the name of the variable - it could be called fred, banana, or tyrannosaurusRex, and it would make no difference. The thing that determines what sort of information you can access through a variable is its type - in this case, KeyboardEvent. If you follow the KeyboardEvent link above, you will see documentation for the KeyboardEvent class, which will tell you all the things you can do with it. For example, one of the properties of KeyboardEvent is keyCode, which tells you which key was pressed:
if (e.keyCode == 32)
{
// 32 is the keyCode for spacebar, so spacebar was pressed
}
import flash.events.KeyboardEvent;
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyboardHandler);
function keyboardHandler(Jack:KeyboardEvent):void{
trace(Jack.keyCode);///----------see output pannel
}
/////////////////--------or
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyboardHandler2);
function keyboardHandler2(Banana:KeyboardEvent):void{
trace(Banana.keyCode);////////----see output pannel
}
You can type anything inside()including KeyboardEvent
You're naming the event that triggers the function, just like any other var it can be named anything. Then, depending on the type of event, you'll have access to a number of vars and function relating to whatever caused the event to trigger.
Edit: Here's what's available to you with a MouseEvent (Public Properties)

Isn't it redundant to declare the data type of an event object in a listener function's parameters?

When you click on the button something happens. However it seems redundant to me that in the declaration of myListenerFunction, the event object e of class MouseEvent, actually has to have its data type MouseEvent mentioned.
mybutton.addEventListener(MouseEvent.CLICK, myListenerFunction);
function myListenerFunction(e:MouseEvent):void
{
// function body
}
Couldn't I get away with this (the .swf works just the same so far as I know...)?
function myListenerFunction(e):void
Since the data type of e should always match the class of the event MouseEvent.CLICK (which is MouseEvent)?
EDIT:
So let's say we go from a mouse event to a keyboard event. By not declaring the data type of e, we can not be prone to errors in not changing the data type of e. e by default is going to be of type KeyboardEvent
mybutton.addEventListener(KeyboardEvent.KEY_DOWN, myListenerFunction);
function myListenerFunction(e):void
{
// function body
}
You can keep the event type to the base class Event if you like. But you will not have access to any of the MouseEvent / KeyboardEvent-specific members when you do it like that.
Using it without a type will make it Object, which is dynamic, meaning you can try to access any member by name (even if it does not exist) - this is slower (a lot) and fairly error prone. You will not get compile time checking for example.