One of those sessions where the JavaScript fundamentals get a little deeper. These concepts — scope, closures — are the kind of things that separate someone who uses JavaScript from someone who actually understands it.
How && Actually Works in JavaScript
Most people think && just returns true or false. It doesn't — it returns one of the actual values. Here's the full picture:
If any value is falsy, it returns that falsy value and stops right there. Doesn't even look at the rest.
If one is truthy and one is falsy, it returns the falsy one.
If both are falsy, it returns the left side — because that's where it stopped.
If both are truthy, it returns the right side — because it evaluated everything and the last truthy value wins.
This is exactly why you see patterns like {isLoggedIn && <Dashboard />} in React. If isLoggedIn is false, && short-circuits and returns false — nothing renders. If it's true, && moves to the right side and returns — which renders. The whole conditional rendering pattern in React is just && doing its thing.
Lexical Scope — Where You Write It Is What Matters
Lexical scope is the rule that decides which variables a function can "see" and access. In JavaScript, an inner function always has access to its parent function's variables — not because of when it runs, but because of where it was written.
The word lexical literally means "at the time of lexing" — which is the phase where JavaScript reads your code before running it. The Lexer walks through your code, sees where variables are declared, and locks in their scope right there and then.
That's also why it's called Static Scope — it doesn't shift. It doesn't matter where or how you call the function later. The scope was decided the moment you wrote it down. No surprises, no dynamic changes.
Closures — The "Backpack" a Function Carries
A closure is what happens when an inner function holds onto its lexical scope even after its parent function has finished running and disappeared from memory.
Normally when a function finishes executing, its local variables get cleaned up. Gone. But if an inner function was returned or stored somewhere — it takes a backpack with it. That backpack contains every variable from the parent's scope that the inner function needs.
`function makeCounter() { let count = 0; return function() { count++; console.log(count); }; }
const counter = makeCounter(); counter(); // 1 counter(); // 2 counter(); // 3
`
makeCounter() finished running. count should be dead. But the returned function still has its backpack — count lives on inside the closure. Every call to counter() reaches into that backpack and updates the same count.
This is one of the most powerful patterns in JavaScript and it shows up everywhere — event handlers, React hooks, module patterns. Once you see the backpack mental model, closures stop feeling scary.
Why Axios Gets Recommended Over fetch
Both do the same job — make HTTP requests. But axios is noticeably nicer to work with day-to-day for two reasons:
Better default response object — when you console.log an axios response, you get a rich object with config, headers, status, request, and your actual data all neatly organised. With fetch you get something much more bare.
No res.json() step — with fetch you always have to do this:
fetch(url) .then(res => res.json()) .then(data => console.log(data));
With axios it's already parsed for you:
axios.get(url) .then(res => console.log(res.data));
One less step every single time. Small thing, but across a whole project it adds up.
Top comments (0)