6 ms·
Track down the JavaScript code responsible for polluting the global scope
- mmazzarolo 5y agoAuthor here! In this post I'll explain a method to debug what JavaScript code is adding global variables to the window object. Hope it can help! Open to questions and feedback.
- throwaway284534 5y agoYour approach is very clever! I think it would be even fancier as a script hosted on a CDN a la Firebug, e.g. https://debugjs.global?var=foobar https://debugjs.global?var=foobar A sort of “Drop this script tag into your app to track down that pesky variable.”
- mmazzarolo 5y agoThank you. That's a nice idea :)
- draaglom 5y agothis is excellent and I will definitely be using it in the future - thankyou!
- sli 5y agoI've known about JS scope lifting for a very long time but even still I had no idea that it would lift iterators in a for-loop all the way to global scope and not just to the function scope without strict mode, that's nuts.
- TekMol 5y agoI often want to do the opposite: I know that the value "HelloWorld123" ends up somewhere in a variable in the global scope. Probably in some variable, nested deep deep down in got knows what. And I want to find it. Is there a good way to go about this?
- mmazzarolo 5y agoIf you don't know the global names, I would probably do something like this: 1. Grab the name of all globals your JS code is creating (using https://mmazzarolo.com/blog/2022-02-14-find-what-javascript-variables-are-leaking-into-the-global-scope/ https://mmazzarolo.com/blog/2022-02-14-find-what-javascript-...). 2. Inspect all of them with the technique used in the article and update the inspection logic so that it checks does a deep check of the value "HelloWorld123" as well (the value can be accessed here: https://gist.github.com/mmazzarolo/2b325f3af2bc83f56d3c921ff0fdeddc#file-globals-debugger-js-L39 https://gist.github.com/mmazzarolo/2b325f3af2bc83f56d3c921ff...)
- jasonkester 5y agoI’ve never really understood why javascript developers hate global scope and state in general. I always make a point of having some form of app object that I can drill into and inspect from the console to see what’s going on anywhere in the application. It just speeds up development so much to be able to know what’s going on without having to set a breakpoint deep in some nest of function calls and hope you’ve been handed some form of scope that tells you what you need. It’s also handy not to have to pass a user object down through every single component in you app so that it trickles down to the corner of the navbar where you’re going to use it. I can certainly understand if you’re publishing a library that other people are going to use, you wouldn’t want to leak out of your own box. But when it’s your own app, it just feels silly to stick in these artificial restrictions so that some junior dev who took a functional class doesn’t make snarky comments.
- mmazzarolo 5y agoTo me, there are two many reasons to avoid the global scope: 1. Like prototype extensions of JS types like "String", you're basically using a namespace that in the future might be used by a built-in API of the JavaScript engine — which would break your code. 2. You don't know for sure where your code will run in the future. A couple of years ago I worked on a migration where "standard" SPA were migrated to a micro-frontend app (where multiple SPA could be loaded on after another at the root level and each SPA would have to clean-up its own globals and listeners). BTW I'm not against it — I DO put some stuff in the global object. If you put your entire state in a namespace like __MY_CUSTOM_SPACE__ the risk of encountering those two issues is basically 0. But I still thing there aren't many valid reasons to do so, especially with nowadays' toolings.
- jasonkester 5y agoOne thing I missed above is "But what about Testing???", since that's a common reason for building things this way. For me, the most important aspects of a codebase are "is it Readable" and "is it Debuggable". In my mind, the problem with building in a functional style for Testability sake is that you have to trade off a lot of Debugability to get there. It's the "know what's going on" bit I wrote above. For me, it's not an acceptable tradeoff. Bug reports come in from users as "debugging requests" rather than unit tests, so I want to optimize for that sort of future work. I actually wrote an article about this a dozen years ago [1] listing my priorities in a codebase, and I don't even think Testable made the list. I'm all for testing where it makes sense, but I'm not going to rearchitect my thing just so that testing is easier. [1] https://www.expatsoftware.com/articles/2007/06/getting-your-priorities-straight.html https://www.expatsoftware.com/articles/2007/06/getting-your-...
- Flimm 5y agoNot all global variables get assigned to the window object. For example: <script> let foo = "bar"; </script> <script> console.log(foo); // prints "bar" console.log(window.foo); // prints "undefined" </script>
- mmazzarolo 5y agoHey! Was this a response to another comment? In the post I'm explaining why it's happening (and it's just purposely bad code to show a global instantiation example)