The classic "print-statement-debugging" techniques may work for simpler cases, but quickly get unmanageable. The checklist below is an extremely effective way to find and fix bugs. Debugging is a learning process - you are about to learn more about your program's behavior and how to translate your ideas into code!
"What makes me think there is a problem?"
"How can I reliably reproduce this problem?" You want the smallest, simplest test case possible that reproduces the bug. The smaller it is, the quicker you will be able to debug it.
""How can I narrow down to the code that could cause this problem?" Tracing through the whole program is not feasible. Instead, consider: Using your intuition as a starting point. Did you change a function recently? Are there any likely culprits? Put console.log at significant point of the program so I can see what’s happening. Ideally, I can spot the problematic code is from that. If not, put console.log at places like half way through the code to get closer to the bug. Console logs being truncated. Check if I need everything in the log and maybe split the log into multiple parts." If you're in GitHub you can use binary search to more easily find the last working version. The explanation is here.
"What information can I gather from this identified code?" Now use consoles.log so I can mentally follow along. Inspect the values of variables and flow of control, and draw pictures. Try externalizing by writing out what I think should be happening, what is happening, and why it's not happening.
Devise and run experiments. "How can I check my hypotheses about the issue?" Make inferences about the root cause and run experiments to validate your hypothesis. Iterate until you identify the root cause.
"How can I fix the issue, and confirm that the fix works?" The fix should be validated by your experiments and passing the original failed test case. You should be able explain the series of facts, tests, and deductions which match the observed symptom to the root cause and the corrected code.