gSkinner - Home

Understanding the Delete Keyword.

Posted on June 20, 2006 by Grant Skinner

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.

Follow @gskinner on Twitter for more news and views on interactive media.
20 Comments

Or trace(delete(o.work)); // traces true, no "work" exists after the delete completes.

Posted by: James Lyon on Jun 20, 2006 12:02pm

James - right. Good addition. I've added it above.

Posted by: Grant Skinner on Jun 20, 2006 12:33pm URL: 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 on Jun 20, 2006 12:37pm URL: 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."

That's how it behaves in AS1/AS2. You can't delete a local variable.

Posted by: Derek Vadneau on Jun 20, 2006 1:43pm 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:

"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."

Posted by: Grant Skinner on Jun 20, 2006 1:47pm 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 ?

(And why MM/Adobe don't provide anything to manage weak references, like they do in EventDispatcher ? )

Posted by: Cédric Néhémie on Jun 20, 2006 2:06pm 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 on Jun 20, 2006 2:12pm URL: 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 on Nov 29, 2007 12:23am URL: 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 on Apr 4, 2008 12:04pm

@Andy

There IS still a reference. You created a reference when you added an event listener.

Posted by: Lanny on Apr 4, 2008 5:37pm URL: http://gskinner.com

Lanny, I thought that the whole purpose of the garbage collector was that IT would remove the event listener for you if you forget to after nulling an object. If we have to remove the event listener, as in you explaination, then what is the use of the garbage collector?

Really confused now!

Posted by: Malc on Dec 17, 2008 9:38am

In Andy's example the Timer instance should be available for cleanup by the garbage collector. Contrary to what Lanny said, there are no active references to it (adding the listener created a reference to the anonymous function from the timer, not the other way around).

What is causing the behaviour you are seeing is the fact that the GC uses a deferred indeterminate model for running cleanups. This means that you have no way of knowing when it will clean up the timer. See my other articles on this subject (search for Resource Management in the side bar) for more information.

Posted by: Grant Skinner on Dec 17, 2008 10:00am URL: http://gskinner.com/blog/

I thought that you had to specify the useWeakReference parameter in addEventListener, since it defaults to false (won't useWeakRefernce ie:

var o:* = {fun:new Timer(100, 100)};

o.fun.addEventListener("timer", function(e:Event) { trace("timer"); }, false, 0, true); // the last true is the weak reference boolean

o.fun.start();

Then delete will actually make it available for GC?

Posted by: Collin Reisdorf on Dec 21, 2008 11:16pm URL: http://blowingthroughlines.com

Sorry to have to re-post so soon but I just remembered the System.gc() method which can be run in the debug player in Flex3, and you don't even need to use the profiler, so it works without Flex Professional!

The following code confirms my thought about useWeakReference in the addEventListener method...

package

{

import flash.display.Sprite;

import flash.events.TimerEvent;

import flash.system.System;

import flash.text.TextField;

import flash.utils.Timer;

public class MaskTester extends Sprite

{

public function MaskTester()

{

var tf:TextField = new TextField();

tf.text = "Garbage Collector Test Running...";

tf.scaleX = tf.scaleY = 5;

tf.autoSize = "left";

this.addChild(tf);

var o:* = {fun:new Timer(1000, 1000)};

o.fun.addEventListener("timer", function(e:TimerEvent):void { trace("o.fun", e.currentTarget.currentCount);

});

o.fun.start();

trace(delete(o.fun));

trace("o.fun", (o.fun));

o.pun = new Timer(1000, 1000)

o.pun.addEventListener("timer", function(e:TimerEvent):void { trace("o.pun", e.currentTarget.currentCount);

},false, 0, true);

o.pun.start();

trace(delete(o.pun));

trace("o.pun", (o.pun));

System.gc();

// traces "fun 1"-1000

// but not "pun 1" -1000

}

}

}

Posted by: Collin Reisdorf on Dec 21, 2008 11:33pm URL: http://blowingthroughlines.com

i have been reading about this for a bit, and i cannot figure out how to completely remove a swf i loaded.

i used

var loader:Loader = new Loader();

loader.load(new URLRequest("mySwf.swf"));

cont.addChild(loader);//cont existing on timeline

then i try removing it like this

cont.removeChildAt(0);

but i can still hear it, i tried using delete() but same thing.

i might be just doing it all the way wrong.

can i have some help please?

Posted by: Jesus on Jan 2, 2009 2:14pm

Does anyone know if timers are ignored by the gc? I've seen posts other places (http://www.bit-101.com/blog/?p=1169#comment-251831) that suggest this. Running a manual gc with a running timer, I can never get the timer to go away. I was under the impression that Timer was like Loader or Tween in that you had to always keep a reference of it to avoid it getting gc'd. I'm thinking now this isn't the case.

Posted by: Drew on Feb 11, 2009 4:18pm

Puh, I m searching now for decades for concret

code snipps/ examples to resolve the memory problems ;-). I learned a lot about defining, removing eventlisteners etc.

BUT:

Please can someone give a code snipp

how to defently remove objects from memory?

And can someone please translate/illustrate this statement with an example:

Make sure you clean up Asynchronous objects directly, nulling these

objects doesn’t unhook them from the Flash player.

- Timer

- Loader

- URLLoader

- File/SQLite

Should we use delete properties to remove an object from memory? I am confused.

Posted by: stevie on Mar 1, 2009 4:30am

stevie, I think you might find what you search here:

http://olegfilipchuk.com/

Posted by: Ced on Nov 17, 2009 9:49pm

What if the dynamically created property is created from a dynamic name? Since the name of the property is dynamic, I can't specify it.

Posted by: Andre Dickson on Aug 3, 2011 12:12pm URL: http://andredickson.net

@Andre Dickson

you can delete the property using the bracket syntax

delete obj["dynamicPropertyName"];

Posted by: Sven on Sep 27, 2011 8:26am

Leave a Reply

Your email is never published nor shared.




You may use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>