JavaScript Interview Questions and Answers
Enjoy 35% off for first-time user! Join the Discord to claim your coupon!
We have digitized the content of this article and trained it into our AIHirely Interview Assistant. You can click the icon in the upper left corner to visit our product homepage. AIHirely is a real-time AI interview assistant that provides AI-generated reference answers to interviewers’ questions during live interviews. Additionally, you can use our AI Mock Interview feature for in-depth practice sessions tailored to your target job position and resume.
Question: What are callback functions in JavaScript?
Answer:
A callback function in JavaScript is a function that is passed as an argument to another function and is executed (called back) at a later time, usually after some operation or event has completed. The callback function is typically invoked once a certain task (such as an asynchronous operation) has finished, allowing JavaScript to handle things in a non-blocking, event-driven manner.
Key Points About Callback Functions:
-
Passed as an Argument : A callback is simply a function that is passed into another function as an argument. The receiving function can then execute the callback at an appropriate time, usually after some asynchronous task is completed or some event is triggered.
-
Asynchronous Nature : Callbacks are often used in asynchronous operations, such as network requests, reading files, or handling user input events. JavaScript, being single-threaded, uses callbacks to ensure that operations that take time (e.g., API calls) don’t block the execution of the rest of the code.
-
Function Execution : Once the asynchronous operation is completed, the callback function is executed, allowing you to handle the result of the operation.
Example of a Callback Function:
function greet(name, callback) {
console.log('Hello, ' + name);
callback(); // Call the callback function
}
function sayGoodbye() {
console.log('Goodbye!');
}
greet('Alice', sayGoodbye);
// Output:
// Hello, Alice
// Goodbye!
- In this example,
sayGoodbye
is passed as a callback to thegreet
function. Aftergreet
logs the greeting, it invokes thesayGoodbye
function.
Callback Functions in Asynchronous Operations:
One of the most common use cases for callback functions is in handling asynchronous operations, like reading files or making HTTP requests.
Example of a callback in an asynchronous operation (using setTimeout
):
console.log('Start');
setTimeout(function() {
console.log('This is inside a callback function!');
}, 2000); // Executes after 2 seconds
console.log('End');
- The code output would be:
Start
End
This is inside a callback function!
- The
setTimeout
function is asynchronous, and it does not block the execution of the code. The callback (insidesetTimeout
) is called after the specified delay (2 seconds), allowing other code (likeconsole.log('End')
) to run in the meantime.
Example with Callback Handling Data:
function fetchData(callback) {
const data = { user: 'John Doe', age: 30 };
// Simulate an asynchronous operation
setTimeout(function() {
callback(data); // Passing data to the callback
}, 1000);
}
function displayUser(data) {
console.log('User:', data.user);
console.log('Age:', data.age);
}
fetchData(displayUser); // Passing the callback function to `fetchData`
- This example simulates an asynchronous data fetch using
setTimeout
. After 1 second, thedisplayUser
callback is called with the fetched data.
Synchronous vs. Asynchronous Callbacks:
- Synchronous Callback : The callback function is executed immediately after the outer function finishes executing. Example:
function processUserData(name, callback) {
console.log('Processing user:', name);
callback(); // Synchronous execution
}
processUserData('Alice', function() {
console.log('User data processed.');
});
Output:
Processing user: Alice
User data processed.
- Asynchronous Callback : The callback function is executed later, after the outer function completes its task (e.g., after an API call or a delay).
Example (with
setTimeout
):
function processUserData(name, callback) {
console.log('Processing user:', name);
setTimeout(callback, 1000); // Asynchronous execution after 1 second
}
processUserData('Bob', function() {
console.log('User data processed.');
});
Output (after 1 second):
Processing user: Bob
User data processed.
Benefits of Callback Functions:
-
Non-blocking : Callbacks enable asynchronous behavior, allowing JavaScript to perform non-blocking operations. This is especially important for operations like network requests, file I/O, and user interactions, which may take time to complete.
-
Event Handling : Callbacks are often used in handling user interactions (click events, keypress events, etc.), allowing developers to specify what should happen when an event occurs.
-
Modular Code : Callbacks can make the code more modular and reusable by allowing one function to be used in multiple contexts.
Callback Hell (Pyramid of Doom):
One of the challenges of using callbacks extensively is that they can lead to deeply nested code (known as callback hell or pyramid of doom ), making the code difficult to read and maintain. Example of callback hell:
doSomething(function(result1) {
doSomethingElse(result1, function(result2) {
doAnotherThing(result2, function(result3) {
// More callbacks nested here...
});
});
});
Solutions to Callback Hell:
-
Promises : Promises are used to handle asynchronous operations more cleanly, chaining actions rather than nesting callbacks.
-
Async/Await : Introduced in ES6,
async/await
provides a more synchronous way to work with asynchronous code, making it easier to read and understand.
Summary:
-
A callback function is a function passed as an argument to another function, which is executed later when a certain task or event is completed.
-
Callbacks are commonly used in asynchronous programming to handle events like data fetching, timers, or user interactions.
-
While callbacks allow for non-blocking operations, they can lead to complex and hard-to-manage code (callback hell), which can be alleviated using Promises or async/await .
Question: What is the event loop in JavaScript?
Answer:
The event loop is a fundamental concept in JavaScript that allows the language to handle asynchronous operations and ensure non-blocking execution. It is part of the JavaScript runtime environment and manages the execution of code, events, and messages in a single-threaded environment. JavaScript is single-threaded, meaning it can execute only one task at a time. However, through the event loop, it can manage asynchronous operations (like I/O tasks, timers, or network requests) without blocking the execution of other code.
Key Concepts of the Event Loop:
-
Single Threaded Model : JavaScript runs in a single thread, meaning that at any given point, only one task can be executed. This is crucial for understanding how asynchronous operations work.
-
Call Stack : The call stack is where the JavaScript engine keeps track of function calls. Each time a function is called, it is added to the stack. Once the function finishes executing, it is removed from the stack. If the stack is not empty, JavaScript will continue executing functions from the top of the stack.
-
Web APIs (or Browser APIs) : These are provided by the browser (or Node.js environment) to handle asynchronous tasks like
setTimeout
, DOM events, or HTTP requests. When an asynchronous operation is initiated, such as a timer or a network request, the Web API handles it, and once the task is completed, it places the corresponding callback function into the callback queue . -
Callback Queue (or Task Queue) : This is where functions (callbacks) that are ready to be executed are placed after their asynchronous operation is completed. Once the call stack is empty, the event loop will move tasks from the callback queue to the call stack for execution.
-
Event Loop : The event loop continuously monitors the call stack and the callback queue. It has a simple job: if the call stack is empty, it moves the first task from the callback queue to the call stack, allowing it to be executed. This is what allows asynchronous tasks to be executed after the synchronous code finishes.
How the Event Loop Works:
-
Execution of Synchronous Code : When JavaScript code is executed, the synchronous code runs first, one statement at a time, and gets pushed to the call stack.
-
Asynchronous Operations : When an asynchronous operation (like
setTimeout
, an API request, or event handling) is encountered, it is handed off to the browser’s Web API (or Node.js APIs). The asynchronous operation is executed outside of the call stack. Once the operation completes, its callback is placed into the callback queue. -
Event Loop Cycle : The event loop checks if the call stack is empty. If it is, the event loop will push the first item from the callback queue to the call stack for execution. This allows the asynchronous code to run after the synchronous code has completed.
Example of the Event Loop in Action:
console.log('Start');
setTimeout(function() {
console.log('Timeout Finished');
}, 2000); // Asynchronous operation, will be placed in the callback queue after 2 seconds
console.log('End');
Execution Flow :
-
console.log('Start')
is executed and logged. -
setTimeout
starts the asynchronous operation, which is handed off to the Web API (browser or Node.js). -
console.log('End')
is executed and logged. -
After 2 seconds, the
setTimeout
callback function is moved from the Web API to the callback queue. -
The event loop checks if the call stack is empty (which it is now), and moves the callback from the queue to the call stack.
-
The callback
console.log('Timeout Finished')
is executed and logged. Output :
Start
End
Timeout Finished
Notice that console.log('Timeout Finished')
appears after 'End'
because setTimeout
is asynchronous and its callback waits in the callback queue until the call stack is clear.
Key Points About the Event Loop:
-
Non-blocking : The event loop allows JavaScript to handle asynchronous code (like file reading, network requests, or timers) without blocking the execution of other code.
-
Single-threaded : JavaScript uses a single thread for execution. However, asynchronous tasks are executed in the background, and their results are placed in the callback queue to be processed later.
-
Handling of Microtasks (Promises) : There is a priority order between tasks in the callback queue. Microtasks (like the resolution of
Promises
) are processed before regular tasks. After the current task in the call stack is completed, the event loop checks the microtask queue before moving to the callback queue.
Event Loop and Microtasks:
-
Microtasks include things like promise resolutions or
MutationObserver
callbacks. -
The event loop processes all the microtasks before continuing with regular tasks in the callback queue. Example :
console.log('Start');
Promise.resolve().then(function() {
console.log('Promise Resolved');
});
setTimeout(function() {
console.log('Timeout Finished');
}, 0);
console.log('End');
Execution Flow :
-
console.log('Start')
is executed. -
The promise resolves immediately, so its
then()
callback is added to the microtask queue . -
setTimeout
starts and places the callback in the callback queue (with 0 delay). -
console.log('End')
is executed. -
The event loop first processes microtasks. The
Promise Resolved
callback is moved from the microtask queue to the call stack and executed. -
Finally, after all microtasks have been processed, the event loop picks up the callback from
setTimeout
and executes it. Output :
Start
End
Promise Resolved
Timeout Finished
Summary:
-
The event loop is a mechanism that allows JavaScript to perform non-blocking operations in a single-threaded environment.
-
It works by continuously checking if the call stack is empty and, if so, moving tasks from the callback queue to the call stack for execution.
-
Asynchronous tasks, such as I/O operations or
setTimeout
, are handled by Web APIs and their callbacks are placed in the callback queue, where they are processed when the call stack is clear. -
Microtasks (e.g., promises) have higher priority than regular tasks and are executed before the event loop picks tasks from the callback queue.
Read More
If you can’t get enough from this article, Aihirely has plenty more related information, such as JavaScript interview questions, JavaScript interview experiences, and details about various JavaScript job positions. Click here to check it out.
Tags:
- JavaScript
- Interview questions
- JavaScript basics
- Closures
- Event loop
- Asynchronous programming
- Callback functions
- Promises
- Async/await
- Prototypal inheritance
- DOM
- Data types
- Error handling
- Arrow functions
- Function expressions
- Function declarations
- Spread operator
- Object cloning
- JavaScript arrays
- Event delegation