Nesting event handlers

by dont_panic

HTML

<script src="https://code.jquery.com/jquery-3.4.1.slim.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.css">
<p><button class="btn btn-success">Click Me!</button></p>

<ul>
<li>On page load, there is only 1 event handler defined, the top-level one - it hasn't actually <i>run</i> yet, so the nested handler isn't yet defined.</li>
<li>On first click, the top-level handler runs, and defines the nested handler</li>
<li>On 2nd click, both handlers run, and a new copy of the nested handler is defined (there are now 2 copies of the nested handler).</li>
<li>On 3rd click, all 3 handlers run.  The log shows the nested handler runs 2x. A new copy of the nested handler is added.</li>
<li>... and so on.  Each click adds a new copy of the nested handler, and they <b>all run</b>.</li>
</ul>

<div class="row">
    <div class="col-sm-6">
        <div>
            <b>Clicks</b>
            <p id="clicks"></p>
        </div>
    </div>
    
    <div class="col-sm-6">
        <div>
            <b>Events</b>
            <p id="events"></p>
        </div>
    </div>
</div>

CSS

.col-sm-6 {
    padding-top: 10px;
    padding-bottom: 10px;
    border: 1px solid #ccc;
}

JavaScript

let $clicks = $('#clicks'), clicks = 0
    $events = $('#events'), topevents = 0, innerevents=0;

// Top-level event handler
$('button').on('click', function() {

    clicks++;
    topevents++;
    
    $clicks.append('<br>Button click #' + clicks);
    $events.append('<br>Top-level event handler run #' + topevents);
    
    // Nested event handler
    $('button').on('click', function() {    
	    innerevents++;
	    $events.append('<br>Inner event handler run #' + innerevents);
    });
});