console.log('Start'); setTimeout(() => console.log('Timeout'), 0); console.log('End');
The synchronous console.log('Start') runs first, then setTimeout schedules the callback to run later, and finally console.log('End') runs. The callback runs after the synchronous code, so the output order is Start, End, Timeout.
The event loop waits for the call stack to be empty and then moves callbacks from the callback queue to the call stack to execute them. This allows asynchronous code to run without blocking synchronous code.
console.log('A'); Promise.resolve().then(() => console.log('B')); console.log('C');
First, console.log('A') runs. Then the promise callback is scheduled as a microtask. Next, console.log('C') runs synchronously. After the synchronous code finishes, the microtask runs, printing B.
setTimeout(() => { console.log(x); let x = 10; }, 0);
The variable x is declared with let after it is accessed. This causes a temporal dead zone error, so accessing x before its declaration throws a ReferenceError.
console.log('1'); setTimeout(() => { console.log('2'); Promise.resolve().then(() => console.log('3')); }, 0); Promise.resolve().then(() => console.log('4')); console.log('5');
First, console.log('1') runs. Then setTimeout schedules a callback. Next, Promise.resolve().then(() => console.log('4')) schedules a microtask. Then console.log('5') runs. After the synchronous code finishes, the microtask runs printing 4. Then the setTimeout callback runs printing 2. Inside it, a promise microtask is scheduled and runs right after the callback finishes, printing 3.