The output will be 3, 3, 3, 0, 1, 2. This example demonstrates a classic closure pitfall and how IIFEs can solve it. In the first loop, by the time the setTimeout callbacks execute (after 1 second), the loop has already completed and the variable i has reached the value 3. Since all three callbacks reference the same variable i through closure, they all log 3. In the second loop, each iteration creates an IIFE that captures the current value of j (as the parameter 'index') and creates a new closure for each timeout function. This way, each callback has its own copy of the loop counter value at the time the IIFE was called, resulting in the output 0, 1, 2. This is a common pattern used before let/const introduced block scoping, which would also solve this problem (using 'let j' instead of 'var j'). This example illustrates how IIFEs can be used to create distinct closure environments.