Select Page

Category: JavaScript

A Bunch of Options for Looping Over querySelectorAll NodeLists

A common need when writing vanilla JavaScript is to find a selection of elements in the DOM and loop over them. For example, finding instances of a button and attaching a click handler to them. const buttons = document.querySelectorAll(".js-do-thing"); // There could be any number of these! // I need to loop over them and attach a click handler. There are SO MANY ways to go about it. Let’s go through them. forEach forEach is normally for arrays, and interestingly, what comes back from querySelectorAll is not an array but a NodeList. Fortunately, most modern browsers support using forEach on NodeLists anyway. buttons.forEach((button) => { button.addEventListener('click', () => { console.log("forEach worked"); }); }); If you’re worried that forEach might not work on your NodeList, you could spread it into an array first: [...buttons].forEach((button) => { button.addEventListener('click', () => { console.log("spread forEach worked"); }); }); But I’m not actually sure if that helps anything since it seems a bit unlikely there are browsers that support spreads but not forEach on NodeLists. Maybe it gets weird when transpiling gets involved, though I dunno. Either way, spreading is nice in case you want to use anything else array-specific, like .map(), .filter(), or .reduce(). A slightly older method is to jack into the array’s natural forEach with this little hack: [], (button) => { button.addEventListener('click', () => { console.log("array forEach worked"); }); });...

Read More

Demystifying JavaScript Testing

Many people have messaged me, confused about where to get started with testing. Just like everything else in software, we work hard to build abstractions to make our jobs easier. But that amount of abstraction evolves over time, until the only ones who really understand it are the ones who built the abstraction in the first place. Everyone else is left with taking the terms, APIs, and tools at face value and struggling to make things work. One thing I believe about abstraction in code is that the abstraction is not magic — it’s code. Another I thing I...

Read More

How to stop using console.log() and start using your browser’s debugger

Whenever I see someone really effectively debug JavaScript in the browser, they use the DevTools tooling to do it. Setting breakpoints and hopping over them and such. That, as opposed to sprinkling console.log() (and friends) statements all around your code. Parag Zaveri wrote about the transition and it has clearly resonated with lots of folks! (7.5k claps on Medium as I write). I know I have hangups about it… Part of debugging is not just inspecting code once as-is; it’s inspecting stuff, making changes and then continuing to debug. If I spend a bunch of time setting up breakpoints, will they still be there after I’ve changed my code and refreshed? Answer: DevTools appears to do a pretty good job with that. Looking at the console to see some output is one thing, but mucking about in the Sources panel is another. My code there might be transpiled, combined, and not quite look like my authored code, making things harder to find. Plus it’s a bit cramped in there, visually. But yet! It’s so powerful. Setting a breakpoint (just by clicking a line number) means that I don’t have to litter my own code with extra junk, nor do I have to choose what to log. Every variable in local and global scope is available for me to look at that breakpoint. I learned in Parag’s article that you...

Read More

New mobile Chrome feature would disable scripts on slow connections

This is a possible upcoming feature for mobile Chrome: If a Data Saver user is on a 2G-speed or slower network according to the NetInfo API, Chrome disables scripts and sends an intervention header on every resource request. Users are shown a UI at the bottom of the screen indicating the page has been modified to save data. Users can enable scripts on the page by tapping “Show original” in the UI. And the people shout: progressive enhancement! Jeremy Keith: An excellent idea for people in low-bandwidth situations: automatically disable JavaScript. As long as the site is built with progressive enhancement, there’s no problem (and if not, the user is presented with the choice to enable scripts). Power to the people! This reminds me of the importance of a very useful building strategy called “Progressive Enhancement” 👀 🙌🏻 — Sara Soueidan (@SaraSoueidan) August 27, 2018 Did you bet on JavaScript or are you gambling with JavaScript? — Zach Leatherman (@zachleat) August 27, 2018 George Burduli reports: This is huge news for developing countries where mobile data packets may cost a lot and are not be affordable to all. Enabling NoScript by default will make sure that users don’t burn through their data without knowledge. The feature will probably be available in the Chrome 69, which will also come with the new Material Design refresh. The post New mobile...

Read More

The Cost of JavaScript in 2018

Even though we mentioned it earlier, I thought this outstanding post by Addy Osmani all about the performance concerns of JavaScript was still worth digging into a little more. In that post, Addy touches on all aspects of perf work and how we can fix some of the most egregious issues, from setting up a budget to “Time-to-Interactive” measurements and auditing your JavaScript bundles. Embrace performance budgets and learn to live within them. For mobile, aim for a JS budget of < 170KB minified/compressed. Uncompressed this is still ~0.7MB of code. Budgets are critical to success, however, they can’t magically fix perf in isolation. Team culture, structure and enforcement matter. Building without a budget invites performance regressions and failure. Super specific and super practical! Surprisingly, Addy mentions that “the median webpage today currently ships about 350KB of minified and compressed JavaScript,” which seems like an awful lot lower than I’d expected, if I’m being honest. The stat that scares me most is that the median webpage takes around fifteen whole seconds until it’s interactive. And pulling all that JS into a Web Worker or caching with Service Workers won’t even make up that time to interaction. Yikes. Another key point: not all bytes are equal. For example, 200KB of JavaScript is not equal to a 200KB JPG image file: A JPEG image needs to be decoded, rasterized, and painted...

Read More