Yesterday was busy, but the girls were so lovely. Alexis bought me breakfast. I had an avocado toast on an everything bagel. Karissa bought me lunch, which was a salad. We dropped Karissa off at school and then went to the audiologist to have Alexis’s hearing aid looked at. It’s not holding a charge, and the speaker makes robotic sounds. Her hearing aid will be ready next week. Of course, she will be back at school, so we need to find a way to get her hearing aid back. Would mailing it be a good idea? We picked up Karissa, went to lunch, and then went to Costco to tighten Alexis’s glasses.
It snowed last night. We had much snow this morning, and the high school was canceled. They never have a snow day anymore; they have remote learning. It’s still snowing out there. I just remembered that I needed stuff to make red velvet cheesecake yesterday, so now I need to find a way to get a car out of the yard to go to the store. It’s not looking very promising at the moment. Oh, Chris needs to go to the store. I could tag along and get the stuff to make cheesecake. He still needs a licensed driver to come with him, and Kel is perfectly content to stay home.
Oh no, Everest chewed the audio extension cable to Tommy’s headphones. I can plug the headphones in directly, but this isn’t good. It was an excellent cable.
Okay, it’s been a few hours. I went to the store during lunch and got the stuff for cheesecake. I also got the numbers 2 and 1 for Lexi’s cake. I told her that she would be turning 12 instead of 21. She agreed with me. Haha.
It stopped snowing, and the roads were clear, which is a good thing. I love the snow, but I’d like the streets to be clear if I go out.
JavaScript notes…
———————————
Decimal to Binary Converter Steps 51 – 80
Step 51
Your call stack is complete. As you can see, a() is at the bottom or beginning of the stack, which calls b() in the middle, which calls c() at the top or end. Once they’re all in place, they begin to execute from top to bottom.
c() executes, returns the string “awesome!”, and is popped off or removed from the top of the stack.
Remove your c(): returns “awesome!” string from the top of the callStack array.
const callStack = [ 'a(): returns "freeCodeCamp " + b()', 'b(): returns "is " + c()', ];
Step 52
Then the function b() executes and evaluates to “is ” + “awesome!”.
Update your mock call to b() so it looks like this: b(): returns “is ” + “awesome!”.
const callStack = [ 'a(): returns "freeCodeCamp " + b()', 'b(): returns "is " + "awesome!"' ];
Step 53
Now that b() has executed, pop it off the call stack. Then, update your mock call to a() to the following: a(): returns “freeCodeCamp ” + “is awesome!”.
const callStack = [ 'a(): returns "freeCodeCamp " + "is awesome!"', ];
Step 54
Finally, a() returns the concatenated string “freeCodeCamp is awesome!”.
Pop a() off the top of the call stack.
const callStack = [ ];
Step 55
While that’s a simple example, it demonstrates how the call stack steps through your code and calls multiple functions.
Now it’s time to jump into recursion, and see how the call stack fits into the picture.
Remove your callStack array, the a(), b(), and c() functions, and the console.log() statement.
(empty)
Step 56
Now you’ll create a function that will count down from a given number to zero using recursion.
Create a new function named countdown with number as a parameter. Leave the function body empty for now.
function countdown (number) { }
Step 57
The first thing you need to do is log the current value of number to the console to act as the countdown.
Use console.log() to log number to the console.
console.log(number)
Step 58
A recursive function is a function that calls itself over and over. But you have to be careful because you can easily create an infinite loop. That’s where the base case comes in. The base case is when the function stops calling itself, and it is a good idea to write it first.
Since your countdown() function will count down from a given number to zero, the base case is when the number parameter is equal to 0. Then it should return to break out of its recursive loop.
Use an if statement to check if number is equal to 0. If it is, use the return keyword to break out of the function.
if (number === 0) { return; }
Step 59
Recursive functions also have a recursive case, which is where the function calls itself.
First, convert your if statement into an if…else statement. Leave the body of your else statement empty for now.
if (number === 0) { return; } else { }
Step 60
When writing the recursive case, you need to remember two things:
What is the base case?
What is the least amount of work you need to do to get closer to the base case?
Since the base case is when number is equal to 0, you need to call countdown() again while also lowering the value of number by 1.
Inside the else block, call countdown() and pass it number – 1 as an argument.
if (number === 0) { return; } else { countdown(number - 1); }
Step 61
It’s time to test your function. Call countdown() with an argument of 3 to see if it works.
countdown(3);
Step 62
To really see the call stack in action, you just need to modify the function slightly.
First, rename the countdown() function to countDownAndUp(). Remember to update your function calls, too.
const countDownAndUp = (number) => { console.log(number); if (number === 0) { return; } else { countDownAndUp(number - 1); } }; countDownAndUp(3);
Step 63
In your base case, log Reached base case to the console.
console.log("Reached base case")
Step 64
Then, log number to the console after your recursive countDownAndUp(number – 1) function call.
countDownAndUp(number - 1); console.log(number)
Step 65
Now you should see a countdown from 3 to 0, followed by Reached base case, and a count from 1 to 3. This is because, after the recursive loop is finished, the function will continue to execute the code after the recursive call. This is why you see Reached base case before the count from 1 to 3.
Now that you have a better understanding of how the call stack and recursion work, you’ll refactor the decimalToBinary() function to use recursion instead of a while loop.
First, remove your countDownAndUp() function and function call.
(empty)
Step 66
Then, remove the contents of your decimalToBinary() function. Leave the body of the function empty for now.
const decimalToBinary = (input) => { };
Step 67
As a reminder, it’s often best to start with the base case when writing a recursive function so you know what you’re working towards, and to prevent an infinite loop.
Similar to your last implementation, you’ll divide input by 2 repeatedly until input is 0.
Use an if statement to check if input is equal to 0. If it is, return an empty string.
if (input === 0) { return ""; }
Step 68
For the recursive case, add an else statement and return the result of calling decimalToBinary(). Pass in input divided by 2 rounded down with Math.floor() as the argument.
if (input === 0) { return ""; } else { return decimalToBinary(Math.floor(input / 2)); }
Step 69
This effectively lowers the input by roughly half each time the decimalToBinary() function is called.
However, remember that the binary number string is built by calculating the remainder of input divided by 2 and concatenating that to the end.
After your call to decimalToBinary(), use the addition operator (+) to concatenate the remainder of input divided by 2 to the end of the string your recursive function returns. Also, wrap the operation in parentheses.
return decimalToBinary(Math.floor(input / 2)) + (input % 2);
Step 70
Finally, in your checkUserInput() function, set the textContent property of result equal to the string returned by your decimalToBinary() function.
result.textContent = decimalToBinary(parseInt(numberInput.value));
Step 71
Your converter should be working now. Feel free to try out different numbers and think about what is happening each time decimalToBinary() is called.
But if you test your converter with 0, you’ll see that nothing happens. This is because you return an empty string in your base case when input is 0. We can fix this now.
Update your base case so that it returns the string “0” when input is equal to 0.
return "0";
Step 72
This mostly works – if you convert 0 into binary, 0 is displayed on the page. But now when you convert other numbers greater than 0, your binary number starts with a leading 0. For example, if you convert 1, the result is 01.
But if you think about it, 0 and 1 in base-10 always convert to 0 and 1 in base-2, respectively. So you can add another base case to handle when input is 1.
Add an else if statement to your function that checks if input is equal to 1. If it is, return the string “1”.
if (input === 0) { return "0"; } else if (input === 1) { return "1"; } else { return decimalToBinary(Math.floor(input / 2)) + (input % 2); }
Step 73
Now everything should work as expected. And since you know that input will either be the numbers 0 or 1 at this point, you can combine your two base cases and just return input as a string.
For a reliable way to convert a value into a string, even falsy values like null and undefined, you can use the String() function. For example:
const num = 5;
console.log(String(num)); // “5”
console.log(String(null)); // “null”
Combine your if and else if statements into a single if statement checking if input is equal to 0 or 1. If it is, use the String() function to convert input into a string and return it.
if (input === 0 || input === 1) { return String(input); } else { return decimalToBinary(Math.floor(input / 2)) + (input % 2); }
Step 74
Now your decimalToBinary() function is complete. Feel free to test it out.
If you’re still confused about how it works under the hood, don’t worry. Next, you’ll create a simple animation to help you understand what’s happening each step of the way.
Create a new function called showAnimation. Leave the body of the function empty for now.
function showAnimation () { }
Step 75
You’ll show the animation when users try to convert the decimal number 5 to binary, so you’ll need to add a check for that within your checkUserInput() function.
Use an if statement to check if the value attribute of numberInput is equal to the number 5. Remember to use the parseInt() function to convert the string into a number before comparing it to 5. Leave the if statement empty for now.
if (parseInt(numberInput.value) === 5) { }
Step 76
If the value of numberInput is equal to 5, call the showAnimation() function, then return early.
showAnimation(); return;
Step 77
Now your showAnimation() function is set up. But if you look closely at your checkUserInput() function, you’ll notice that it’s not very DRY – you’re calling parseInt() to convert numberInput.value into a number several times.
A simple way to fix this is to create a new variable to store the converted number. Then you only have to convert the number once and can use it throughout the function.
Create a new variable called inputInt and assign it the number converted from numberInput.value.
const inputInt = parseInt(numberInput.value);
Step 78
Replace all instances of parseInt(numberInput.value) with inputInt.
const inputInt = parseInt(numberInput.value); if (!numberInput.value || isNaN(inputInt)) { alert("Please provide a decimal number"); return; } if (inputInt === 5) { showAnimation(); return; } result.textContent = decimalToBinary(inputInt); numberInput.value = "";
Step 79
Now that your showAnimation() function is set up, let’s do some testing.
Add three console.log() statements in the showAnimation() function to log the text free, Code, and Camp to the console. You should see that text in the console when you enter 5 into the number input and click the Convert button.
console.log("free"); console.log("Code"); console.log("Camp");
Step 80
Before you start writing code for the animation, let’s take a look at the function you’ll use to add and remove elements from the DOM: setTimeout.
The setTimeout function takes two arguments: a callback function and a number representing the time in milliseconds to wait before executing the callback function.
For example, if you wanted to log Hello, world! to the console after 3 seconds, you would write:
setTimeout(() => {
console.log(“Hello, world!”);
}, 3000);
Use the setTimeout function to add a one second delay before the text Code is logged to the console. Then see what happens after you enter 5 into the number input and click the Convert button.
setTimeout(() => { console.log("Code"); }, 1000);