In the comments of my previous post about how the garbage collector works in Flash Player 9, Cédric Néhémie asked a great question about why using delete on a property of a sealed (non-dynamic) class throws an error in ActionScript 3, and whether it will delete the actual object in memory.
There isn't a lot of documentation on this topic, and what there is is hard to find, so much the following is conjecture and interpolation from related exploration, but I think it is fairly accurate. If not, please let me know in the comments - I don't want to lead anyone astray.
My understanding is that the delete keyword deletes the actual variable definition, not just the variable's value. This of course frees any reference it was holding, potentially freeing that object for garbage collection (as described in my previous article). It will not delete the referenced object from memory directly.
ActionScript 2
In AS2, this behaviour was virtually unnoticeable, as the player did not have support for sealed (non-dynamic) classes at run-time. This meant that deleting a variable definition was functionally almost identical to setting the variable's value to undefined. Because of this, the compiler never bothered throwing errors related to delete. There were only a few rare cases where differences could be seen. For example, in AS2 try deleting a MovieClip instance's onPress handler and mousing over the clip. Now try setting its onPress to undefined. Even though tracing onPress will return "undefined" in either case, you will get a hand cursor on the one you set to undefined but not on the one you deleted. I'm quite sure this is because the player looks for the existence of the onPress handler definition, not a value, when determining if it should show the hand cursor.
ActionScript 3
AS3 on the other hand supports sealed classes at run-time. All classes are sealed by default, unless they are explicitly declared to be dynamic. You may not modify the definition of a sealed class (or its instances) by adding or removing members at run-time. Because of this, and to comply with the ECMAScript specification, delete will only remove dynamically created properties of dynamic classes. It will not even remove local (method level) variables. This is alluded to in the "What's new for the PrintJob class using ActionScript 3.0" doc (for whatever reason):
In ActionScript 2.0, you could use delete to remove an object or on an object property. In ActionScript 3.0, the delete operator is now ECMAScript compatible, meaning delete can only be used on a dynamic property of an object.
If you try to use delete on anything other than a dynamic property, it will trigger a compiler error (in strict mode) that looks something like this:
1189 > Delete removes dynamically defined properties from an object. Declared properties of a class can not be deleted. This error appears only when the compiler is running in strict mode.
In AS3, delete will return a boolean value indicating whether it was successful (ie. the property no longer exists when the operation completes). You can test this with the following code:
var t:* = new Timer(15); // no typing to get around the compiler error trace(delete(t.delay)); // traces false, object is sealed so can't delete trace(t.delay); // 15 - delete never occurred var o:* = {fun:"stuff"}; trace(delete(o.fun)); // traces true, object is dynamic so can delete trace(o.fun); // undefined - delete occurred trace(delete(o.foo)); // true, because foo is not defined after delete
UPDATE: Added information to the article about delete returning a boolean success value.
UPDATE 2: Rewrote some sections slightly based on new information found in the AS3 docs.
Comments (10)
Or trace(delete(o.work)); // traces true, no "work" exists after the delete completes.
Posted by: James Lyon at June 20, 2006 12:02 PMURL:
James - right. Good addition. I've added it above.
Posted by: Grant Skinner at June 20, 2006 12:33 PMURL: http://gskinner.com/
I forgot to mentionned that I've got the same error with a local variable :
var o:Object = new Object();
trace (delete (o)); // trace false
trace (o); // [object Object]
It's like the only goal of delete keyword in AS3 is to remove a dynamically defined property from a dynamic class.
Strange isn't it ?
Posted by: Cédric Néhémie at June 20, 2006 12:37 PMURL: http://book.abe.free.fr
"It's like the only goal of delete keyword in AS3 is to remove a dynamically defined property from a dynamic class."
Posted by: Derek Vadneau at June 20, 2006 01:43 PMThat's how it behaves in AS1/AS2. You can't delete a local variable.
URL: http://tracethis.com
Doing some more digging, I've found that that's actually exactly right Cédric. From (of all places) the PrintJob documentation for AS3:
Posted by: Grant Skinner at June 20, 2006 01:47 PM"In ActionScript 2.0, you could use delete to remove an object or on an object property. In ActionScript 3.0, the delete operator is now ECMAScript compatible, meaning delete can only be used on a dynamic property of an object."
URL: http://gskinner.com/
"That's how it behaves in AS1/AS2. You can't delete a local variable."
You're right, sorry for the mistake, sometimes I don't think enough :P
And nom the question is : How we can delete an object stored in a sealed class property ?
Posted by: Cédric Néhémie at June 20, 2006 02:06 PM(And why MM/Adobe don't provide anything to manage weak references, like they do in EventDispatcher ? )
URL: http://book.abe.free.fr
Cédric - you can never specifically delete an object. You can null the value of the property though, which deletes the reference to the object.
Weak references will be the topic of one of my upcoming articles. You're getting ahead of me here. :)
Posted by: Grant Skinner at June 20, 2006 02:12 PMURL: http://gskinner.com/
Please Help!!
I'm busy building a media player that loads an external swf containg a FLVPlayback component.
In the players 'collapsed' state, I need to delete the MovieClip declared in my class declaration: private var _videoPlayerMc:MovieClip;
I get the following error:
1189: Attempt to delete the fixed property _videoPlayerMc. Only dynamically defined properties can be deleted.
How can i go about doing this?
Posted by: Yuri at November 29, 2007 12:23 AMURL: http://www.theliblab-tutorials.com
Doesn't really clear up any issues with the garbage collector, though. It deletes the reference, sure, but items are still not being flagged for GC. Don't know why. See:
var o:* = {fun:new Timer(100, 100)};
o.fun.addEventListener("timer", function(e:Event) { trace("timer"); });
o.fun.start();
trace(delete(o.fun));
trace(o.fun);
Output:
true
undefined
timer
timer
timer
timer
... (repeats 100 times)
The timer, which longer has any references AFAICT, is not being collected.
Posted by: Andy at April 4, 2008 12:04 PMURL:
@Andy
Posted by: Lanny at April 4, 2008 05:37 PMThere IS still a reference. You created a reference when you added an event listener.
URL: http://gskinner.com