title: jQuery .remove() vs Node.removeChild() and external maps to DOM nodes
body: <p>The jQuery API documentation for jQuery <a href="https://api.jquery.com/remove/" rel="nofollow"><code>.remove()</code></a> mentions:</p>
  
  <blockquote>
    <p>In addition to the elements themselves, all bound events and jQuery
    data associated with the elements are removed.</p>
  </blockquote>
  
  <p>I assume "bound events" here means "event handlers"; documentation for the similar <a href="https://api.jquery.com/empty/" rel="nofollow"><code>.empty()</code></a> says:</p>
  
  <blockquote>
    <p>To avoid memory leaks, jQuery removes other constructs such as data
    and event handlers from the child elements before removing the
    elements themselves.</p>
  </blockquote>
  
  <p>It does sound like leaks would ensue if one were to <strong>not</strong> use these functions and use <a href="https://developer.mozilla.org/en-US/docs/Web/API/Node.removeChild" rel="nofollow"><code>Node.removeChild()</code></a> (or <a href="https://developer.mozilla.org/en-US/docs/Web/API/ChildNode.remove" rel="nofollow"><code>ChildNode.remove()</code></a>) instead.</p>
  
  <p>Is this true for modern browsers?</p>
  
  <ul>
  <li>If so, why exactly can't properties and event handlers be collected once the node is removed?</li>
  <li>If not, do we still need to use <a href="https://api.jquery.com/data/" rel="nofollow">.data()</a>? Is it only good to retrieve HTML5 <code>data-</code> attributes?</li>
  </ul>
  
  <p>Documentation for <a href="https://api.jquery.com/jQuery.data/" rel="nofollow"><code>jQuery.data()</code></a> (lower-level function) says:</p>
  
  <blockquote>
    <p>The jQuery.data() method allows us to attach data of any type to DOM
    elements in a way that is safe from circular references and therefore
    free from memory leaks. jQuery ensures that the data is removed when
    DOM elements are removed via jQuery methods, and when the user leaves
    the page.</p>
  </blockquote>
  
  <p>This sounds an awful lot like a solution to the old IE <a href="http://www.javascriptkit.com/javatutors/closuresleak/index3.shtml" rel="nofollow">DOM/JS circular leak pattern</a> which, AFAIK, is solved in all browsers today.</p>
  
  <p>However, a comment in the jQuery <a href="https://github.com/jquery/jquery/blob/master/src/data.js" rel="nofollow"><code>src/data.js</code></a> code (<a href="https://github.com/jquery/jquery/blob/30eee925dbc9f8d465ccf064f48c24061ffdc378/src/data.js" rel="nofollow">snapshot</a>) says:</p>
  
  <blockquote>
    <p>Provide a clear path for implementation upgrade to WeakMap in 2014</p>
  </blockquote>
  
  <p>Which suggests that the idea of storing data strictly associated to a DOM node outside of the DOM using a separate data store with a map is still considered in the future.</p>
  
  <p><strong>Is this just for backward-compatibility, or is there more to it?</strong></p>
  
  <p>Answers provided to other questions like <a href="https://stackoverflow.com/questions/1160193/using-jquerys-datastore-vs-expando-properties">this one</a> also seem to imply that the sole reason for an external map is to avoid cyclic refs between DOM objects and JS objects, which I consider irrelevant in the context of this question (unless I'm mistaken).</p>
  
  <p>Furthermore, I've seen plugins that now set properties on relevant DOM nodes directly (e.g. <a href="https://github.com/brianreavis/selectize.js" rel="nofollow">selectize.js</a>) and it doesn't seem to bother anyone. Is this an OK practice? It certainly looks that way, as it makes removing entire DOM trees very easy. No need to walk it down, no need to clean up any external data store, just detach it from the parent node, lose the reference, and let the garbage collector do its thing.</p>
  
  <h3>Further notes, context and rationale to the question:</h3>
  
  <p>This kind of capability is especially interesting for frameworks that manage views (e.g. <a href="http://durandaljs.com/" rel="nofollow">Durandal</a>), which often times have to replace entire trees that represent said views in their architecture. While most of them certainly support jQuery explicitly, this solution does not scale at all. Every component that uses a similar data store must also be cleaned up. In the case of Durandal, it seems they (at least in one occurrence, the <a href="https://github.com/BlueSpire/Durandal/blob/master/src/plugins/js/dialog.js" rel="nofollow">dialog plugin</a> - <a href="https://github.com/BlueSpire/Durandal/blob/58cc44791515309bea5a435a8f149c65b0f79a90/src/plugins/js/dialog.js" rel="nofollow">snapshot</a>) rely on Knockout's <a href="https://github.com/knockout/knockout/blob/master/src/utils.domNodeDisposal.js" rel="nofollow"><code>.removeNode()</code></a> (<a href="https://github.com/knockout/knockout/blob/ae6856189bb558d5d4b1f4867602045784f5aad5/src/utils.domNodeDisposal.js" rel="nofollow">snapshot</a>) utility function, which in turn uses jQuery's <a href="https://stackoverflow.com/questions/7083884/what-is-the-purpose-of-jquery-clean-and-cleandata-methods">internal <code>cleanData()</code></a>. That's, IMHO, a prime example of horrible special-casing (I'm not sure it even works as it is now if jQuery is used in noConflict mode, which it is in most AMD setups).</p>
  
  <p><strong>This is why I'd love to know if I can safely ignore all of this or if we'll have to wait for <a href="http://w3c.github.io/webcomponents/" rel="nofollow">Web Components</a> in order to regain our long-lost sanity.</strong></p>