javascriptmemory-managementgarbage-collectionjavascript-objects

Why do JavaScript Websocket objects not get destroyed when they go out of scope?


In JavaScript, when you do something like this,

function connect() {

    var ws = new WebSocket(url);

    ws.onmessage = function(e) {
        window.alert(e.data);
    };
}

it will work. But why is that?

You would expect that after the connect() function exits, that local ws object goes out of scope and is garbage collected. But in JavaScript, this does not happen.

So does it have something to do with the ws object having event listeners attached to it? Or what is the reason the object continues to stay in memory?


Solution

  • Does it have something to do with the ws object having event listeners attached to it?

    Yes, precisely. As long as the socket connection is open, the runtime (browser engine) should call those event listeners when an event happens. So it needs to hold onto this event listener (or the entire WebSocket instance, as that'll technically become the .target of the event), and this reference is what keeps it from getting garbage-collected. Only when there are no listeners, or no more events (because the socket was closed), the runtime can stop holding onto the instance, since it can be certain it won't be needed any longer.

    This works pretty much the same for all asynchronous web APIs, whether it's network (WebSocket, XMLHttpRequest, fetch, RTCPeerConnection, …), timers (setTimeout, setInterval, requestAnimationFrame, …), file system (FileReader, …), or the whole DOM (document) itself. The runtime has a list of "active" objects that serve as the garbage collection roots, to keep your application alive after its initial setup code has been executed.