Search code examples
javascriptjqueryhtmljquery-clone

How does this closure work when using JQuery clone() and selecting descendant element


In the below code when the user clicks the "click me" div a new list item is "cloned" and it works the way I would expect.

JSfiddle_1

HTML

  <div class="button">Click me</div>
        <div class="template">
            <li>oink</li>
        </div>

    <ul>
    </ul>

JavaScript

$(".button").on("click",function(){

    var result = $('.template li').clone(); //______Descendant selector
    $("ul").append(result);
});

However, in the version of the code below I modified the code to not have a descendant selector. In this version when you click the "click me" div the number of elements is compounded on each click which tells me a closure is happening, but what I don't understand is why this doesn't happen when adding a descendant selector. Any clarification is appreciated. Thank you

JSfiddle_2

HTML

<div class="button">Click me</div>
    <div class="template">
        <li>oink</li>
    </div>

<ul>
</ul>

JavaScript

$(".button").on("click",function(){

    var result = $('li').clone(); //______No descendant selector
    $("ul").append(result);
});

Solution

  • $('.template li') selects descendant <li>s of just the .template <div> which is just one in your case. This is what Descendant selector is used for - To get specific elements, instead of all.

    $(".button").on("click",function(){
    
        var result = $('.template li').clone(); //______Descendant selector
        $("ul").append(result);
    });
    

    While just $('li') selects <li>s from the whole DOM (initial + newly appended). The number of li elements resulting from $('li') will increase with the append.

    $(".button").on("click",function(){
        var result = $('li:first').clone(); //______No descendant selector
        $("ul").append(result);
    });
    

    HTML at 2nd click, you can see there are two<li> at this point of time. So $('li') appends two elements and so on.

    <div class="button">Click me</div>
    <div class="template">
        <li>oink</li>
    </div>
    
    <ul>
        <li>oink</li>
    </ul>