Learning jQuery 1.4: Remove() vs. Detach()

Posted January 20, 2010 at 9:49 AM

Tags: Javascript / DHTML

A few years ago, I found out that using the jQuery methods, empty() and remove(), would unbind any existing event handlers on the given nodes in an attempt to prevent memory leaks. As I was reading up on the changes implemented in jQuery 1.4, however, I found out that the remove() method would also erase any data associated with the given node (data that had been originally set using the data() method). This was news to me; but, it wasn't a new feature added in jQuery 1.4 - the new feature I was reading about was detach(). The detach() method does the same thing as remove(), only it doesn't alter any of the data()-bound node information. In other words, all associated data and event bindings remain associated to the given node even after it is removed from the DOM (document object model).

 
 
 
 
 
 
 
 
 
 

To see this in action, I have created a page with two links. Both of these links will be removed from the DOM and then subsequently reattached. One will be removed using jQuery's remove() method and the other one will be removed using jQuery's new detach() method. Additionally, a live-click event handler will be attached to both links such that a data-point associated to the given node - nickname - can be logged to the console. In this way, we can see how both event bindings and data bindings are affected by each node-removal technique.

 Launch code in new window » Download code as text file »

  • <!DOCTYPE HTML>
  • <html>
  • <head>
  • <title>jQuery 1.4: Remove() vs. Detach()</title>
  • <script type="text/javascript" src="jquery-1.4.js"></script>
  • <script type="text/javascript">
  •  
  • // When the DOM is ready, initialize scripts.
  • jQuery(function( $ ){
  •  
  • // Set up a live click event on the links on this
  • // page so we can alert the data of a link even
  • // if it's event handler has been removed.
  • $( "a" ).live(
  • "click",
  • function(){
  • var trigger = $( this );
  •  
  • // Log the nickname.
  • console.log(
  • trigger.attr( "class" ),
  • " : ",
  • trigger.data( "nickname" )
  • );
  • }
  • );
  •  
  •  
  • // Get a reference to the links.
  • var removeMe = $( "a.remove" );
  • var detachMe = $( "a.detach" );
  •  
  • // Give each link a nickname so that we can see how
  • // the data is affected after each remove / detach.
  • removeMe.data( "nickname", "Big Sexy" );
  • detachMe.data( "nickname", "Hot Stuff" );
  •  
  •  
  • // Get a continer reference.
  • var container = $( "p" );
  •  
  •  
  • // Bind click event handlers.
  • removeMe.click(
  • function(){
  • console.log( "RemoveMe... removed" );
  •  
  • // Remove element using REMOVE method.
  • removeMe.remove();
  •  
  • // Re-attach to the document in after a
  • // short delay.
  • setTimeout(
  • function(){
  • container.prepend( removeMe );
  • },
  • 1000
  • );
  • }
  • );
  •  
  • // Bind click event handlers.
  • detachMe.click(
  • function(){
  • console.log( "DetachMe... detached" );
  •  
  • // Remove element using DETACH method.
  • detachMe.detach();
  •  
  • // Re-attach to the document in after a
  • // short delay.
  • setTimeout(
  • function(){
  • container.append( detachMe );
  • },
  • 1000
  • );
  • }
  • );
  •  
  • });
  •  
  • </script>
  • </head>
  • <body>
  •  
  • <h1>
  • jQuery 1.4: Remove() vs. Detach()
  • </h1>
  •  
  • <p>
  • <a href="#" class="remove">Remove Me</a>
  • &nbsp;&nbsp;|&nbsp;&nbsp;
  • <a href="#" class="detach">Detach Me</a>
  • </p>
  •  
  • </body>
  • </html>

To demonstrate this, I am going to click on the "Remove Me" link three times in a row; then, I'm going to click on the "Detach Me" link three times in a row. After doing that, here is what we get:

 
 
 
 
 
 
Learning jQuery 1.4: Remove() vs. Detach(). 
 
 
 

As you can see, the "Remove Me" click event handler fired only once. After that, not only did the click event handler stop working, the data associated with the node - nickname - became undefined. This is because the remove() method removes all data associated to the given node, including event bindings. On the other hand, the "Detach Me" click event handler fired every time; and, its "nickname" remained defined. This is because the new detach() method does not alter the node data when it is removed from the DOM.

jQuery's new detach() method seems very cool; however, I'm trying to think about why I have not needed it in the past. I think my reliance on hide/show techniques in conjunction with event delegation (whether through live() or other means) has really given me most of what I used to want to get out of remove(). Now that we have detach(), however, it will be interesting to see if and how I start thinking differently about problems.

Download Code Snippet ZIP File

Post Comment  |  Ask Ben  |  Print Page





Reader Comments

Jan 20, 2010 at 10:35 AM // reply »
2 Comments

Thanks for posting this one with explaining everything in a video! Thats definately very very helpful. Thanks for that

Hans


Jan 20, 2010 at 7:49 PM // reply »
1 Comments

smart sample code and well explained! thanks :)


Jan 20, 2010 at 10:30 PM // reply »
7,539 Comments

Thanks guys - glad you found this useful.


Jan 22, 2010 at 1:27 AM // reply »
1 Comments

just came across this blog. I liked it. :)


Jan 22, 2010 at 8:30 AM // reply »
1 Comments

Yup that's correct most of the time we just use .hide() if we want to remove an object.


Jan 22, 2010 at 6:04 PM // reply »
1 Comments

wanted to comment on the post, that I liked that fact you have a good writeup with explanation, and code samples. I really hate watching videos and screencasts, but I know others might like it. I think its cool you provided both.


Jan 22, 2010 at 8:57 PM // reply »
7,539 Comments

@Cease,

Thanks. I try to make the videos only as a "supplement" to the writing of the post. It sounds like that is a best-of-both worlds approach, especially as there are people, like yourself, who are not crazy about videos.


Jan 25, 2010 at 1:12 AM // reply »
1 Comments

Great Video, thank you!The detach implementation takes advantage of the remove using a keepData flag under the hood:)


Jan 25, 2010 at 7:47 PM // reply »
1 Comments

Correct me if I'm wrong, but the way I understand it is that if you want remove an element from the DOM in order to manipulate it (say you want to change all the values in a certain column. Doing that while the table is still on the DOM is a very expensive step. Thus, you would remove the table from the DOM, manipulate it in whichever way you see fit, and then reinsert it into the DOM), in which case simple show()/hide() wouldn't do. So, up until now you had to remove() it, manipulate it, and then maybe append(), or whatever. But then you lose all of you data associated with it. But now, in jQuery 1.4, you could just use detach()...

Just my way of understanding it. I might be wrong....


Jan 25, 2010 at 9:01 PM // reply »
7,539 Comments

@Doug,

Thanks - good to know about the keepData flag.

@Joe,

Yes, that's entirely accurate. If you are going to be making a lot of DOM changes, it is recommended for performance that you remove it from the DOM, make those changes, and then re-attach it to the DOM. With detach(), that is now much easier (if you are mutating an object with lots of data and event bindings).


Post Comment  |  Ask Ben

Recent Blog Comments
Mar 18, 2010 at 6:34 PM
Exploring ColdFusion Component Runtime Class Properties And Serialization
@Ben Very useful analyses. Thank you @Elliot Thanks for additional clarification Though, it's quite a shame that getBust() failed...not defined ;) ... read »
Mar 18, 2010 at 5:35 PM
Exploring ColdFusion Component Runtime Class Properties And Serialization
Saving private properties is necessary so that you can "reconstitute" an object on the other side of the wire, or load up a serialized object you saved to disk. If it didn't save the private state o ... read »
Mar 18, 2010 at 4:04 PM
jQuery's Event Triggering, Order Of Default Behavior, And triggerHandler()
Tks! You saved-me today. it can be chained into one statement: $("#x).attr("checked","checked").triggerHandler('click'); ... read »
Mar 18, 2010 at 1:18 PM
Finally Finished Ayn Rand's Atlas Shrugged Audio Book
@joaopft, Not disputing what you say - but... If I understand you correctly, you are saying that Positivism is based on sense experience (what I experience is what is), but Quantum theory states tha ... read »
Mar 18, 2010 at 11:48 AM
Duplicate() Much Faster Than ColdFusion Query-of-Queries
I am working on a massive xml parsing, qofq app to create 2 seperate xml files. I just don't understand the concept/purpose of duplicate function, are you duplicating the data or the row, into a new ... read »
Mar 18, 2010 at 11:22 AM
Exploring ColdFusion Component Runtime Class Properties And Serialization
@Zarko, Ha ha, you know ColdFusion is my first love ;) ... read »
Mar 18, 2010 at 11:15 AM
Exploring ColdFusion Component Runtime Class Properties And Serialization
Hi Ben, nice to have you back! I already gave up on you, thinking you'll write about jQuery and iPhone for the rest our our lives! :) ... read »
Mar 18, 2010 at 10:36 AM
Ask Ben: Javascript Replace And Multiple Lines / Line Breaks
@Ben Nadel, Hey Ben, thanks for you're response. It works!! However.. if you could please kindly look at http://edeals.zzl.org/divchange2.php where I am trying it out you will see that with the " ... read »