<div id="container">
  <div id="codeSection">
    <div id="code">
      <code id="func">
        <pre>

            <span class="outerFunc">function sum(<span class="vars">list</span>){</span>
    
                <span id="baseCase">if(list.length === 0) <span id="baseCaseReturn">return 0;</span></span>
    
                return <span id="retList">list[<span class="retListVar">0</span>]</span> + <span id="recFunc">sum(<span class="vars">list.slice(1)</span>);</span>
            <span class="outerFunc">}</span>

            const <span class="res">result</span> = <span id="mainFunc">sum([2, 4, 6])</span>;

            console.log(<span class="res">result</span>); <span id="result" class="res"> // 12 </span>
        </pre>
      </code>
    </div>
    <div id="controls">
      <ul>
        <li><a href="#" id="WALKTHROUGH_prev">&#x3c;</a></li>
        <li id="controlsInfo"></li>
        <li><a href="#" id="WALKTHROUGH_next">&#x3e;</a></li>
      </ul>
    </div>
  </div>
  <div id="main">
    <div id="stack">
      <div id="header">
        <p>Call stack</p>
      </div>
      <div class="block">
        <p class="func">sum()</p>
        <p><span class="vars">list: [ ]</span></p>
      </div>
      <div class="block">
        <p class="func">sum()</p>
        <p>
          <span class="vars">list: [<span class="retListVar">6</span>]</span>
        </p>
      </div>
      <div class="block">
        <p class="func">sum()</p>
        <p>
          <span class="vars">list: [<span class="retListVar">4</span>, 6]</span>
        </p>
      </div>
      <div class="block">
        <p class="func">sum()</p>
        <p>
          <span class="vars">list: [<span class="retListVar">2</span>, 4, 6]</span>
        </p>
      </div>
    </div>
    <div id="info">
      <div></div>
    </div>
  </div>
</div>
* {
  margin: 0;
  padding: 0;
}
h2,
h4,
.block,
#header p,
#info div p {
  font-family: Arial, Helvetica, sans-serif;
}
h2 {
  float: none;
  font-size: large;
  margin: 25px;
}
#codeSection {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top:25px;
}
#code {
  background-color: #f8f8f8;
  border: black;
  white-space: normal;
  min-width: 50%;
  font-size: large;
}
pre {
  margin: 15px;
  
  white-space: pre-wrap;
word-wrap: break-word;
}
#main {
  display: flex;
  justify-content: center;
  margin-top: 20px;
}
#stack {
  display: flex;
  flex-direction: column;
  border: 1px solid black;
  width: 300px;
  padding-bottom: 10px;
  min-height: 300px;
}
#info {
  width: 300px;
  display: flex;
}

.block {
  font-size: small;
  text-align: center;
  margin: 10px;
  border: 1px solid black;
  background: #f8f8f8;
  border-radius: 3%;
  display: none;
}
.block p.func,
#header p {
  border-bottom: 1px solid black;
  font-size: medium;
}

.block p {
  font-size: medium;
}

#header p {
  padding: 10px;
  text-align: center;
}

.block p {
  padding: 5px 0;
}
#controls ul {
  list-style: none;
  padding: 10px 0;
}
#controls ul li {
  display: inline;
  font-size: larger;
  padding: 0 20px;
}
#controls ul li a {
  text-decoration: none;
  color: black;
}
#info div p,
#info div h4 {
  padding: 5px 10px;
}
a.disabled {
  opacity: 0.2;
  cursor: default;
}
#result {
  display: none;
}
const recWalkThrough = (function () {
  let slidePosition = 0;

  const zero = () => {
    $("#controlsInfo").text("0 / 9");
    $("#WALKTHROUGH_prev").addClass("disabled");
    $("#mainFunc").css("color", "black");
    $(".outerFunc").css("color", "black");
    $("#info div").html("").hide();
    $(".block").eq(3).hide();
    $("#info div")
      .html(
        "<h4>The Call Stack</h4><p>JavaScript uses a call stack to manage execution contexts: the global and function execution contexts.</p> <p>The call stack uses the LIFO principle (Last In First Out)<p> <p>Whenever a function is called, a function execution context is created and is pushed to the top of the call stack, and starts executing the function.</p>"
      )
      .fadeIn();
    $(".outerFunc .vars").css("color", "black");
  };

  const first = () => {
    $("#controlsInfo").text("1 / 9");
    $("#WALKTHROUGH_prev").removeClass("disabled");
    $("#info div")
      .html(
        "<p>On execution of the sum function, the call stack is allocated a block of memory for the function and its variables are stored.</p>"
      )
      .fadeIn();
    $(".block")
      .eq(3)
      .fadeIn()
      .css("borderColor", "green")
      .children("p")
      .css({ borderColor: "green", color: "green" });
    $("#mainFunc").css("color", "green");
    $(".outerFunc").css("color", "green");
    $("#recFunc").css("color", "black");
    $("#recFunc .vars").css("color", "black");
    $(".outerFunc .vars").css("color", "green");
    $(".block").eq(3).find(".retListVar").css("color", "green");
  };

  const second = () => {
    $(".block")
      .eq(3)
      .fadeIn()
      .css("borderColor", "green")
      .children("p")
      .css({ borderColor: "green", color: "green" });
    $("#mainFunc").css("color", "green");
    $(".outerFunc").css("color", "green");
    $(".block").eq(2).hide();
    $("#controlsInfo").text("2 / 9");
    $("#info div").hide();
    $("#info div")
      .html(
        '<p>Because an <span style="color:orange">inner sum function</span> is executed inside the <span style="color:green">main sum function</span> the <span style="color:green">main sum function\'s</span>  execution is paused.</p>'
      )
      .fadeIn("slow");
    $("span.vars").css("color", "green");

    $("#recFunc").css("color", "orange");
    $("#recFunc .vars").css("color", "orange");
    $(".block").eq(3).find(".retListVar").css("color", "green");
  };

  const third = () => {
    $("#controlsInfo").text("3 / 9");
    $("#mainFunc").css("color", "black");
    $(".outerFunc").css("color", "orange");
    $(".block")
      .eq(3)
      .fadeIn()
      .css("borderColor", "black")
      .children("p")
      .css({ borderColor: "black", color: "black" });
    $(".block")
      .eq(2)
      .fadeIn()
      .css("borderColor", "orange")
      .children("p")
      .css({ borderColor: "orange", color: "orange" });
    $("#info div")
      .html(
        '<p>A new block of memory is pushed to the top of the stack and the <span class="vars">variables passed</span> are saved to memory. </p><p><span class="vars">list.slice(1)</span> just removes the first element of the array.</p>'
      )
      .fadeIn("slow");
    $("span.vars").css("color", "red");
    $(".block").eq(3).find("span.vars").css("color", "black");
    // $('.outerFunc .vars').css('color', 'orange');
    $(".block").eq(1).fadeOut();
    $(".block").eq(2).find(".retListVar").css("color", "red");
  };

  const forth = () => {
    $("#controlsInfo").text("4 / 9");

    $(".block")
      .eq(2)
      .css("borderColor", "black")
      .children("p")
      .css({ borderColor: "black", color: "black" });
    $(".block span.vars").css("color", "black");
    $("#info div").html(
      "<p>As another inner sum function is hit the process is repeated.<p><p>The parent sum function is stopped from fully executing and another block is added to the top of the stack.</p>"
    );
    $(".block").eq(2).find("span.vars").css("color", "black");

    $(".block")
      .eq(1)
      .fadeIn()
      .css("borderColor", "orange")
      .children("p")
      .css({ borderColor: "orange", color: "orange" });
    $(".block").eq(1).find("span.vars").css("color", "red");
    $(".block").eq(0).fadeOut();
    $("#recFunc").css("color", "orange");
    $("#recFunc span.vars").css("color", "red");
    $("#baseCase").css("color", "black");

    $("#baseCaseReturn").css("color", "black");
    $(".retListVar").eq(1).css("color", "red");
    $(".block").eq(2).find(".retListVar").css("color", "black");
  };

  const fifth = () => {
    $("#controlsInfo").text("5 / 9");

    $(".block")
      .eq(1)
      .css("borderColor", "black")
      .children("p")
      .css({ borderColor: "black", color: "black" });
    $(".block span.vars").css("color", "black");
    $("#info div").html(
      '<p>Another inner sum function is executed, but this time we hit our <span style="color:purple">all important base case</span>.</p><p><em>Without a base case, a recursive function will generally end up causing an infinite loop. </em></p><p>As the <span style="color:red">list</span> length is found to be 0, the function <span style="color:purple">returns 0</span>, an the call stack completes execution and removes the memory from the stack.  </p>'
    );
    $(".block").eq(2).find("span.vars").css("color", "black");

    $(".block")
      .eq(0)
      .fadeIn()
      .css("borderColor", "orange")
      .children("p")
      .css({ borderColor: "orange", color: "orange" });
    $(".block").eq(0).find("span.vars").css("color", "red");
    $("#recFunc").css("color", "black");
    $("#recFunc .vars").css("color", "black");
    $("#baseCase").css("color", "purple");
    $("#baseCaseReturn").css("color", "purple");
    $(".outerFunc").css("color", "orange");
    $(".outerFunc span.vars").css("color", "red");
    $("#retList").css("color", "black");
    $(".retListVar").eq(0).css("color", "red");
    $(".retListVar").eq(1).css("color", "black");
    $("#retList .retListVar").css("color", "black");
  };

  const sixth = () => {
    $("#controlsInfo").text("6 / 9");
    $(".block")
      .eq(1)
      .fadeIn()
      .css("borderColor", "orange")
      .children("p")
      .css({ borderColor: "orange", color: "orange" });
    $(".block").eq(1).find("span.vars").css("color", "red");
    $(".block").eq(0).fadeOut();
    $("#recFunc").css("color", "purple");
    $("#recFunc span.vars").css("color", "purple");
    $("#baseCase").css("color", "black");
    $("#baseCaseReturn").css("color", "black");
    $("#info div").html(
      '<p>Now the call stack continues to complete the other partially executed functions one by one from the top of the stack (remember LIFO on step 0). </p> <p>So for this block, we can see the return statement adds the <span style="color:blue">first element</span> in the <span style="color:red">list</span> to the value returned from the <span style="color:purple">sum function previously executed in step 5</span> (which we know <span style="color:purple">returned 0</span>). </p><p> This function now returns 6 to the parent sum function that executed it.</p>'
    );
    $("#retList").css("color", "red");
    $(".retListVar").css("color", "blue");
    $(".block").eq(2).find(".retListVar").css("color", "black");
    $(".outerFunc").css("color", "black");
    $(".outerFunc .vars").css("color", "black");
    $(".block")
      .eq(2)
      .css("borderColor", "black")
      .children("p")
      .css({ borderColor: "black", color: "black" });
    $(".block").eq(2).find("span.vars").css("color", "black");
    $(".block").eq(3).find(".retListVar").css("color", "black");
  };

  const seventh = () => {
    $("#controlsInfo").text("7 / 9");
    $(".block").eq(0).find("span.vars").css("color", "red");
    $(".block").eq(2).find("span.vars").css("color", "red");
    $(".block").eq(1).fadeOut();
    $(".block")
      .eq(2)
      .fadeIn()
      .css("borderColor", "orange")
      .children("p")
      .css({ borderColor: "orange", color: "orange" });
    $("#recFunc").css("color", "purple");
    $("#recFunc span.vars").css("color", "purple");
    $("#baseCase").css("color", "black");
    $("#baseCaseReturn").css("color", "black");
    $("#info div").html(
      '<p>The next block, in turn, is now completed and the list\'s <span style="color:blue">first item value</span> is added to the <span style="color:purple">previous sum function\'s return value which was six</span>.</p> <p>This now returns 10 to the parent sum function which executed it.</p>'
    );
    $("#retList").css("color", "red");
    $(".block").eq(2).find(".retListVar").css("color", "blue");
    $(".block").eq(3).find(".retListVar").css("color", "black");
    $(".outerFunc").css("color", "black");
    $(".outerFunc .vars").css("color", "black");
    $(".block")
      .eq(3)
      .css("borderColor", "black")
      .children("p")
      .css({ borderColor: "black", color: "black" });
    $(".block").eq(3).find("span.vars").css("color", "black");
  };

  const eighth = () => {
    $("#controlsInfo").text("8 / 9");
    $(".block").eq(2).fadeOut();
    $(".block")
      .eq(3)
      .fadeIn()
      .css("borderColor", "green")
      .children("p")
      .css({ borderColor: "green", color: "green" });
    $(".block").eq(3).find("span.vars").css("color", "red");
    $(".retListVar").css("color", "blue");
    $("#info div").html(
      '<p>We return to the very first sum function.</p><p>It in turn gets completed and adds the list\'s <span style="color:blue">first item value</span> to the <span style="color:purple">previous sum function\'s return value which was 10</span>.</p>'
    );
    $("#WALKTHROUGH_next").removeClass("disabled");
    $(".res").css("color", "black");
    $("#result").hide();
    $("#retList").css("color", "red");
    $("#recFunc").css("color", "purple");
    $("#recFunc .vars").css("color", "purple");
  };

  const ninth = () => {
    $("#controlsInfo").text("9 / 9");
    $("#WALKTHROUGH_next").addClass("disabled");
    $(".block").eq(3).fadeOut();
    $(".res").css("color", "green");
    $("#result").show();
    $("#retList").css("color", "black");
    $(".retListVar").css("color", "black");
    $("#recFunc").css("color", "black");
    $("#recFunc .vars").css("color", "black");
    $("#info div").html(
      '<p>Returning our <span style="color:green">result 12</span> to the intial invoking function, which in this case just gets assigned to a constant and then is written to the console.</p>'
    );
  };

  const slide = () => {
    switch (slidePosition) {
      case 0:
        return zero();
      case 1:
        return first();
      case 2:
        return second();
      case 3:
        return third();
      case 4:
        return forth();
      case 5:
        return fifth();
      case 6:
        return sixth();
      case 7:
        return seventh();
      case 8:
        return eighth();
      case 9:
        return ninth();
    }
  };

  const next = (e) => {
    e.preventDefault();
    if (e.currentTarget.className) return;
    slidePosition++;
    slide();
  };

  const prev = (e) => {
    e.preventDefault();
    if (e.currentTarget.className) return;
    slidePosition--;
    slide();
  };

  return {
    zero,
    first,
    next,
    prev
  };
})();

$(function () {
  $("a#WALKTHROUGH_next").on("click", (e) => recWalkThrough.next(e));
  $("a#WALKTHROUGH_prev").on("click", (e) => recWalkThrough.prev(e));
  recWalkThrough.zero();
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js