<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"><</a></li>
<li id="controlsInfo"></li>
<li><a href="#" id="WALKTHROUGH_next">></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();
});
This Pen doesn't use any external CSS resources.