Explanation
What you've run into can be found in this question.
setTimeout, in simple english, basically delays the execution of its callback function to the "next tick" of the execution.
Basically, the execution context is parsed and queued up. When the browser executes any setTimeout, the browser queues its callbacks to the end of the execution queue.
See the code below for extra understanding.
Using setTimeout
console.log('Queue', 1, '`timeout` function is defined.');
timeout = function(cb){
console.log('Queue', 3, '`timeout` function is executed.');
setTimeout(cb, 0);
}
console.log('Queue', 2, '`timeout` function is called');
timeout(function(){
console.log('Queue', 5, '`timeout` callback is executed.');
console.log(message)
});
console.log('Queue', 4, '`messeage` variable is defined.');
let message = 'Ok.';
If you see the sequence of the logging, you can see that the value of message variable is already available when the cb is executed.
NOT using setTimeout
Now, compared the above code to this code below, you can see that without setTimeout, the cb execution is not "queued" behind but is called instantly. Making the initialisation execution of message variable execute after cb is called (which throws an error).
console.log('Queue', 1, '`timeout` function is defined.');
timeout = function(cb){
console.log('Queue', 3, '`timeout` function is executed.');
cb();
}
console.log('Queue', 2, '`timeout` function is called');
timeout(function(){
console.log('Queue', 5, '`timeout` callback is executed.');
console.log(message)
});
console.log('Queue', 4, '`messeage` variable is defined.');
let message = 'Ok.';