ECMAScript 6 class destructor

I know ECMAScript 6 has constructors but is there such a thing as destructors for ECMAScript 6?

For example if I register some of my object's methods as event listeners in the constructor, I want to remove them when my object is deleted.

One solution is to have a convention of creating a destructor method for every class that needs this kind of behaviour and manually call it. This will remove the references to the event handlers, hence my object will truly be ready for garbage collection. Otherwise it'll stay in memory because of those methods.

But I was hoping if ECMAScript 6 has something native that will be called right before the object is garbage collected.

If there is no such mechanism, what is a pattern/convention for such problems?


Solution 1:

Is there such a thing as destructors for ECMAScript 6?

No. EcmaScript 6 does not specify any garbage collection semantics at all[1], so there is nothing like a "destruction" either.

If I register some of my object's methods as event listeners in the constructor, I want to remove them when my object is deleted

A destructor wouldn't even help you here. It's the event listeners themselves that still reference your object, so it would not be able to get garbage-collected before they are unregistered.
What you are actually looking for is a method of registering listeners without marking them as live root objects. (Ask your local eventsource manufacturer for such a feature).

1): Well, there is a beginning with the specification of WeakMap and WeakSet objects. However, true weak references are still in the pipeline [1][2].

Solution 2:

I just came across this question in a search about destructors and I thought there was an unanswered part of your question in your comments, so I thought I would address that.

thank you guys. But what would be a good convention if ECMAScript doesn't have destructors? Should I create a method called destructor and call it manually when I'm done with the object? Any other idea?

If you want to tell your object that you are now done with it and it should specifically release any event listeners it has, then you can just create an ordinary method for doing that. You can call the method something like release() or deregister() or unhook() or anything of that ilk. The idea is that you're telling the object to disconnect itself from anything else it is hooked up to (deregister event listeners, clear external object references, etc...). You will have to call it manually at the appropriate time.

If, at the same time you also make sure there are no other references to that object, then your object will become eligible for garbage collection at that point.

ES6 does have weakMap and weakSet which are ways of keeping track of a set of objects that are still alive without affecting when they can be garbage collected, but it does not provide any sort of notification when they are garbage collected. They just disappear from the weakMap or weakSet at some point (when they are GCed).


FYI, the issue with this type of destructor you ask for (and probably why there isn't much of a call for it) is that because of garbage collection, an item is not eligible for garbage collection when it has an open event handler against a live object so even if there was such a destructor, it would never get called in your circumstance until you actually removed the event listeners. And, once you've removed the event listeners, there's no need for the destructor for this purpose.

I suppose there's a possible weakListener() that would not prevent garbage collection, but such a thing does not exist either.


FYI, here's another relevant question Why is the object destructor paradigm in garbage collected languages pervasively absent?. This discussion covers finalizer, destructor and disposer design patterns. I found it useful to see the distinction between the three.


Edit in 2020 - proposal for object finalizer

There is a Stage 3 EMCAScript proposal to add a user-defined finalizer function after an object is garbage collected.

A canonical example of something that would benefit from a feature like this is an object that contains a handle to an open file. If the object is garbage collected (because no other code still has a reference to it), then this finalizer scheme allows one to at least put a message to the console that an external resource has just been leaked and code elsewhere should be fixed to prevent this leak.

If you read the proposal thoroughly, you will see that it's nothing like a full-blown destructor in a language like C++. This finalizer is called after the object has already been destroyed and you have to predetermine what part of the instance data needs to be passed to the finalizer for it to do its work. Further, this feature is not meant to be relied upon for normal operation, but rather as a debugging aid and as a backstop against certain types of bugs. You can read the full explanation for these limitations in the proposal.