A browser's console is a place where JavaScript programmers spend a lot of time. And for good reason - it's a very helpful tool to dig into your code. When I first started writing JavaScript I was told that there are two easy methods for debugging code: a browser's built-in 'debugger' (providing a break-point in your code), or writing a 'console.log' when you need to confirm a variable's value.
I started my journey committing my loyalty to the debugger. I liked that the debugger provided ultimate flexibility - I assumed I had all the benefits of a console.log with so much more. Being dropped into a specific function meant I could see the value of each of its variables and any larger-scope variables. This is where I was wrong.
What I discovered was that outer-scope variables that are not called in the inner-scope are not available to the debugger tool.
let outsideFunVar = "π€π€π€";
function hopeThisWorks() {
debugger
}
The above debugger call will not provide access to the variable 'outsideFunVar' because it is not called on the same level as the function containing the debugger. Simply calling the variable before the debugger, as shown below, will provide access.
let outsideFunVar = "π€π€π€";
function hopeThisWorks() {
outsideFunVar
debugger
}
Oddly, one solution to this problem is to utilize a JavaScript feature that is heavily frowned upon - the built-in 'eval' function. The 'eval' function will execute the string passed to it as JavaScript and allows our debugger to see all variables in the local context. Demonstrated with the code below...
let outsideFunVar = "π€π€π€";
function hopeThisWorks() {
eval('debugger');
}
The eval function is not advised due to the danger of running potentially harmful scripts. If your program uses the eval function, and a malicious user is able to inject a script, the script could expose or alter data that would otherwise be hidden from the user.
The crux of this problem seems to be related to how a browser optimizes performance for an end user. Variables are organized to be used immediately or to wait on the sidelines. The variables that need to be accessed are stored on the 'heap' or in context objects, while outside variables are stored on the stack.
Stack variables are not visible to the debugger, but this tradeoff is intentional. If all variables were kept on the heap, that would make most programs very memory-expensive. If a program doesn't manage memory efficiently, serving that program on a large scale will either require vast resources (e.g. RAM), or it will perform very slowly. For high-level languages like Ruby and JavaScript, small optimizations such as this are critical for optimizing runtime as well as resource consumption.
Diving into this question gave me a greater appreciation for the importance of memory management, and exposed me to various types of memory (e.g. heap, stack). This exercise also shed light on how many optimizations are made to improve the user experience.
...Also, maybe a console.log is okay every once in a while.
Sources:
eval(), by MDN web docs
Why does Chrome debugger think closed local variable is undefined?, courtesy of stackoverflow user Louis
Top comments (0)