Demystifying Function Declarations Within Conditional Blocks
In the two previous posts in this series about hoisting, we talked about how function declarations - using the function keyword - are hoisted along with their definitions. This means we can call such a function BEFORE its code even appears, and it will execute.
Now we will delve into the nuances related to hoisting function declarations within conditional blocks. The path our function declaration might take is based on the environment in which we operate.
In many languages, when you declare a function inside a conditional block (like an if
statement), it's conditionally created, i.e., the function is only declared if the block is executed.
JavaScript behaves differently (of course!) when it comes to function declarations (using the function
keyword) inside conditionals.
Here's a simple example:
if (false) {
function testFunction() {
console.log("This is a test function.");
}
}
testFunction();
Expectation: Since the condition is false
, the code inside won't run, and thus the function won't be declared.
The reality of JavaScript: it depends!
In some environments, calling testFunction()
after this block might work, because of hoisting.
Here's how this behavior varies depending on the JavaScript environment:
ES5 and non-strict mode: The function declaration is hoisted out of the block and to the top of the enclosing function or global scope, irrespective of the conditional. This means
testFunction
would be available both before the block's start and after its end, throughout the enclosing function or global scope.ES6 (ES2015) and later in strict mode: Block-level function declarations are now defined per the ES6 specification, which means the function is block-scoped, just like
let
andconst
. So in this case, trying to calltestFunction
outside the block will throw an error because the function was not hoisted outside of the block.
This is a subtle yet important distinction, and the reason why we often see recommendations to avoid using function declarations inside blocks (instead, use function expressions or arrow functions).
Main Takeaway
While traditional function declarations are hoisted to the top of their scope, when used inside conditional blocks, their behavior can vary based on the ECMAScript version and mode (strict vs. non-strict).
Resources
Subscribe to my newsletter
Read articles from Corina Murg directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Corina Murg
Corina Murg
I am a self-taught software engineer with a background in math teaching. As a teacher my focus was on creating learning experiences that were inclusive and accessible. For that reason, the frontend's concern with accessible web products deeply resonates with me. I am excited to collaborate on projects with developers from all over the world, and engage in conversations about our responsibility to ensure that every user feels seen and valued. I believe in a web where everyone has a place!