Top 50 Vital Advanced JavaScript Interview Questions & Answers!
1. What is the Event Loop in JavaScript?
Answer: The Event Loop is a mechanism that allows JavaScript to perform non-blocking operations by offloading operations to the system kernel whenever possible. JavaScript is single-threaded, meaning it can do one thing at a time. The Event Loop checks the call stack and if it's empty, it takes the first task from the callback queue and pushes it onto the call stack, thus ensuring asynchronous callbacks are executed.
2. Explain closures and provide an example.
Answer: A closure is a function that remembers its lexical scope even when the function is executed outside that lexical scope. This allows the function to access variables from its enclosing scope even after that scope has finished executing.
function outerFunction() { let outerVariable = 'I am outside!'; function innerFunction() { console.log(outerVariable); } return innerFunction; } const myFunction = outerFunction(); myFunction(); // logs 'I am outside!'
3. What are Promises and why are they used?
Answer: Promises are used to handle asynchronous operations in JavaScript. They represent a value that may be available now, or in the future, or never. Promises provide a more readable and cleaner way to handle asynchronous code compared to traditional callback methods.
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Success!');
}, 1000);
});
promise.then((value) => {
console.log(value); // logs 'Success!' after 1 second
});
4. What is the difference between var, let, and const?
Answer:
- var: Function-scoped, can be redeclared, hoisted.
- let: Block-scoped, cannot be redeclared, not hoisted.
- const: Block-scoped, cannot be redeclared, must be initialized, not hoisted.
5. Explain the concept of hoisting in JavaScript.
Answer: Hoisting is JavaScript's default behavior of moving declarations to the top of the current scope. This means variable and function declarations are processed before any code is executed.
console.log(hoistedVar); // undefined var hoistedVar = 'This variable is hoisted'; console.log(notHoistedLet); // ReferenceError: notHoistedLet is not defined let notHoistedLet = 'This variable is not hoisted';
6. What are async/await and how do they relate to Promises?
Answer: async and await are syntactic sugars built on top of Promises to write asynchronous code in a more synchronous-looking manner. An async function returns a Promise. The await keyword can be used to wait for a Promise to resolve before proceeding with the next line of code.
async function fetchData() { let response = await fetch('https://api.example.com/data'); let data = await response.json(); return data; }
7. Describe the concept of "this" in JavaScript.
Answer: The value of this in JavaScript depends on the context in which a function is called:
- In a method, this refers to the owner object.
- Alone, this refers to the global object.
- In a function, this refers to the global object (in non-strict mode) or undefined (in strict mode).
- In an event, this refers to the element that received the event.
8. What are arrow functions and how do they differ from regular functions?
Answer: Arrow functions are a shorter syntax for writing functions. They do not have their own this context; instead, they inherit this from the parent scope.
// Regular function function add(a, b) { return a + b; } // Arrow function const add = (a, b) => a + b;
9. Explain the difference between == and ===.
Answer:
- == (abstract equality): Compares two values for equality, after converting both values to a common type.
- === (strict equality): Compares two values for equality without type conversion.
0 == false; // true 0 === false; // false
10. What is the purpose of the bind method?
Answer: The bind method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
0 == false; // true 0 === false; // false
11. What are higher-order functions?
Answer: Higher-order functions are functions that take other functions as arguments or return them as output. They are often used for abstraction and code reuse.
function greaterThan(n) { return function(m) { return m > n; }; } let greaterThan10 = greaterThan(10); console.log(greaterThan10(11)); // true
12. Explain the concept of currying.
Answer: Currying is a process in functional programming where a function with multiple arguments is transformed into a sequence of functions each taking a single argument.
function add(a) { return function(b) { return a + b; }; } let add5 = add(5); console.log(add5(2)); // 7
13. What are prototypes in JavaScript?
Answer: Prototypes are the mechanism by which JavaScript objects inherit properties and methods. Every JavaScript object has a prototype, which is also an object.
function Person(name) { this.name = name; } Person.prototype.greet = function() { console.log('Hello, ' + this.name); }; let person = new Person('John'); person.greet(); // logs 'Hello, John'
14. What is the purpose of Object.create?
Answer: Object.create is used to create a new object with a specified prototype object and properties.
let personPrototype = { greet: function() { console.log('Hello, ' + this.name); } }; let john = Object.create(personPrototype); john.name = 'John'; john.greet(); // logs 'Hello, John'
15. Explain the call and apply methods.
Answer: Both call and apply methods are used to invoke a function with a specific this context. The difference lies in how arguments are passed:
- call: Arguments are passed individually.
- apply: Arguments are passed as an array.
function greet(greeting, punctuation) { console.log(greeting + ', ' + this.name + punctuation); } let person = { name: 'John' }; greet.call(person, 'Hello', '!'); // logs 'Hello, John!' greet.apply(person, ['Hi', '.']); // logs 'Hi, John.'
16. What is Function.prototype.bind used for?
Answer: Function.prototype.bind creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
let person = { name: 'John', greet: function() { console.log('Hello, ' + this.name); } }; let greet = person.greet.bind(person); greet(); // logs 'Hello, John'
17. What are IIFEs (Immediately Invoked Function Expressions)?
Answer: IIFEs are functions that are executed immediately after they are defined. They create a local scope and avoid polluting the global namespace.
(function() { console.log('IIFE executed'); })();
18. What are modules in JavaScript and why are they important?
Answer: Modules are reusable pieces of code that can be imported and exported. They help in organizing code, reducing namespace pollution, and managing dependencies.
// In module.js export function greet(name) { console.log('Hello, ' + name); } // In main.js import { greet } from './module.js'; greet('John'); // logs 'Hello, John'
19. What is strict mode in JavaScript?
Answer: strict mode is a way to opt into a restricted variant of JavaScript, which helps catch common coding errors and prevents the use of certain unsafe features.
'use strict'; function myFunction() { // Code in this function is in strict mode }
20. Explain the concept of Debouncing in JavaScript.
Answer: Debouncing is a technique used to ensure that a function is not called too frequently. It limits the rate at which a function executes, ensuring it runs after a specified delay since the last call.
function debounce(func, wait) { let timeout; return function() { clearTimeout(timeout); timeout = setTimeout(() => func.apply(this, arguments), wait); }; } window.addEventListener('resize', debounce(() => { console.log('Resized'); }, 200));
21. What is throttling in JavaScript?
Answer: Throttling is a technique that ensures a function is called at most once in a specified period of time. This is useful for limiting the number of times a function is executed over time, such as during scrolling or resizing events.
function throttle(func, limit) { let inThrottle; return function() { const args = arguments; const context = this; if (!inThrottle) { func.apply(context, args); inThrottle = true; setTimeout(() => inThrottle = false, limit); } }; } window.addEventListener('resize', throttle(() => { console.log('Resized'); }, 200));
22. What are Generators in JavaScript?
Answer: Generators are functions that can be paused and resumed. They are defined using the function* syntax and use the yield keyword to yield values.
function* generatorFunction() { yield 'Hello'; yield 'World'; } const generator = generatorFunction(); console.log(generator.next().value); // 'Hello' console.log(generator.next().value); // 'World'
23. Explain async and await in JavaScript.
Answer: async and await are syntactic sugars over Promises, making asynchronous code look synchronous. An async function always returns a Promise, and await is used to wait for a Promise to resolve.
async function fetchData() { let response = await fetch('https://api.example.com/data'); let data = await response.json(); return data; } fetchData().then(data => console.log(data));
24. What is the purpose of Promise.all and Promise.race?
Answer:
- Promise.all: Waits for all promises to resolve or for any to reject.
- Promise.race: Waits for the first promise to resolve or reject.
const promise1 = Promise.resolve(3); const promise2 = new Promise((resolve, reject) => setTimeout(resolve, 100, 'foo')); Promise.all([promise1, promise2]).then(values => { console.log(values); // [3, 'foo'] }); Promise.race([promise1, promise2]).then(value => { console.log(value); // 3 });
25. Explain this keyword in arrow functions.
Answer: Arrow functions do not have their own this context; they inherit this from the parent scope in which they are defined. This makes them especially useful for writing callbacks.
const person = { name: 'John', greet: function() { setTimeout(() => { console.log('Hello, ' + this.name); }, 1000); } }; person.greet(); // 'Hello, John'
26. What are the differences between ES5 and ES6?
Answer: ES6 (ECMAScript 2015) introduced many new features compared to ES5, such as:
- Arrow functions
- Classes
- Template literals
- Default parameters
- Rest and spread operators
- Let and const
- Promises
- Modules
- Destructuring assignment
27. Explain the map, filter, and reduce array methods.
Answer:
- map: Creates a new array with the results of calling a provided function on every element.
- filter: Creates a new array with all elements that pass the test implemented by the provided function.
- reduce: Executes a reducer function on each element of the array, resulting in a single output value.
const numbers = [1, 2, 3, 4, 5]; const doubled = numbers.map(n => n * 2); console.log(doubled); // [2, 4, 6, 8, 10] const evens = numbers.filter(n => n % 2 === 0); console.log(evens); // [2, 4] const sum = numbers.reduce((acc, n) => acc + n, 0); console.log(sum); // 15
28. What is NaN and how can you check for it?
Answer: NaN stands for Not-a-Number. It is a value that represents a computational error. You can check for NaN using the isNaN function or Number.isNaN.
console.log(NaN === NaN); // false console.log(isNaN(NaN)); // true console.log(Number.isNaN(NaN)); // true
29. Explain the concept of memoization.
Answer: Memoization is an optimization technique used to speed up function execution by storing the results of expensive function calls and returning the cached result when the same inputs occur again.
function memoize(fn) { const cache = {}; return function(...args) { const key = JSON.stringify(args); if (cache[key]) { return cache[key]; } const result = fn(...args); cache[key] = result; return result; }; } const fibonacci = memoize(function(n) { if (n <= 1) return n; return fibonacci(n - 1) + fibonacci(n - 2); }); console.log(fibonacci(40)); // Much faster than non-memoized version
30. What are service workers?
Answer: Service workers are scripts that run in the background, separate from the web page, enabling features like push notifications and background sync. They are also key to building Progressive Web Apps (PWAs).
// Registering a service worker if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/service-worker.js') .then(registration => { console.log('Service Worker registered with scope:', registration.scope); }) .catch(error => { console.log('Service Worker registration failed:', error); }); }
31. What is the fetch API?
Answer: The fetch API provides a more powerful and flexible replacement for the XMLHttpRequest object for making network requests.
fetch('https://api.example.com/data') .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error));
32. Explain Proxy and Reflect in JavaScript.
Answer:
- Proxy: Allows you to create a proxy object that can intercept and redefine operations for another object.
- Reflect: Provides a set of static methods for performing operations that reflect those of the proxy handlers.
let target = { message: 'Hello, world!' }; let handler = { get: function(target, property) { return property in target ? target[property] : `No such property as '${property}'`; } }; let proxy = new Proxy(target, handler); console.log(proxy.message); // 'Hello, world!' console.log(proxy.nonExistentProperty); // 'No such property as 'nonExistentProperty''
33. What is the difference between localStorage and sessionStorage?
Answer:
- localStorage: Stores data with no expiration time. Data is not cleared when the browser is closed.
- sessionStorage: Stores data for the duration of the page session. Data is cleared when the page session ends.
// localStorage localStorage.setItem('key', 'value'); console.log(localStorage.getItem('key')); // 'value' // sessionStorage sessionStorage.setItem('key', 'value'); console.log(sessionStorage.getItem('key')); // 'value'
34. What is WebAssembly?
Answer: WebAssembly (Wasm) is a binary instruction format for a stack-based virtual machine. It is designed as a portable target for the compilation of high-level languages like C, C++, and Rust, enabling deployment on the web for client and server applications.
35. What is a WeakMap and how is it different from a Map?
Answer:
- WeakMap: A collection of key-value pairs where keys are objects and values can be arbitrary values. The keys in a WeakMap are weakly referenced, meaning they do not prevent garbage collection.
- Map: A collection of key-value pairs where keys and values can be of any type, and keys are strongly referenced.
let weakMap = new WeakMap(); let obj = {}; weakMap.set(obj, 'value'); obj = null; // Now the entry is eligible for garbage collection let map = new Map(); map.set('key', 'value'); map.delete('key'); // Must manually delete entries
36. Explain the Symbol type in JavaScript.
Answer: Symbol is a primitive data type introduced in ES6. Each symbol is unique and immutable, often used to create unique property keys for objects.
const sym1 = Symbol('description'); const sym2 = Symbol('description'); console.log(sym1 === sym2); // false
37. What is Object.defineProperty and why would you use it?
Answer: Object.defineProperty allows you to define a new property directly on an object or modify an existing property. You can control the property's configuration such as its value, writability, enumerability, and configurability.
let obj = {}; Object.defineProperty(obj, 'key', { value: 'value', writable: true, enumerable: true, configurable: true }); console.log(obj.key); // 'value'
38: Explain the concept of prototypal inheritance in JavaScript.
Answer: Prototypal inheritance in JavaScript is based on prototypes, where each object has a prototype object from which it inherits properties. When a property is accessed on an object, JavaScript first looks for the property on the object itself. If it's not found, it looks at the object's prototype, and this chain continues until the property is found or the end of the prototype chain is reached (i.e., the prototype is null). This mechanism allows objects to inherit and override properties from their prototypes, facilitating code reuse and a flexible object-oriented programming style in JavaScript.
// Parent constructor function function Person(name, age) { this.name = name; this.age = age; } // Adding a method to the prototype of Person Person.prototype.sayHello = function() { console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`); }; // Child constructor function inheriting from Person function Student(name, age, grade) { Person.call(this, name, age); // Call the parent constructor this.grade = grade; } // Inheriting the prototype of Person Student.prototype = Object.create(Person.prototype); // Adding a method specific to Student Student.prototype.study = function(subject) { console.log(`${this.name} is studying ${subject} in grade ${this.grade}.`); }; // Creating instances of Person and Student let john = new Person('John', 30); let jane = new Student('Jane', 20, 12); // Using inherited methods john.sayHello(); // Outputs: Hello, my name is John and I am 30 years old. jane.sayHello(); // Outputs: Hello, my name is Jane and I am 20 years old. jane.study('Math'); // Outputs: Jane is studying Math in grade 12.
In this example:
- Person is a constructor function defining a name and age properties, with sayHello method added to its prototype.
- Student is a constructor function that inherits from Person using Object.create(Person.prototype) and adds a grade property and a study method.
- Instances of Person (john) and Student (jane) demonstrate how Student inherits properties and methods from Person through the prototype chain.
Question 39: What are closures in JavaScript? Provide an example of how they are used.
Answer: Closures in JavaScript refer to the combination of a function and its lexical environment, which allows the function to access variables from its outer scope even after the outer function has finished executing. Closures are created whenever a function is defined within another function, and the inner function retains access to the variables and parameters of the outer function.
Example:
function outerFunction() { let outerVar = 'I am outer'; function innerFunction() { console.log(outerVar); // Accessing outerVar from the outer scope } return innerFunction; } const closureExample = outerFunction(); closureExample(); // Logs: I am outer
Question 40: How does JavaScript handle asynchronous operations? Explain the event loop.
Answer: JavaScript uses an event-driven, single-threaded model to handle asynchronous operations. Asynchronous operations, such as fetching data from a server or executing a timeout, are handled using callbacks, promises, and async/await syntax.
The event loop is a fundamental part of this model, responsible for managing the execution of multiple tasks in a single thread. It continuously checks the call stack and task queue. When the call stack is empty, it takes the first task from the queue and pushes it onto the call stack, executing it. This process allows JavaScript to handle non-blocking I/O operations efficiently, ensuring responsiveness in applications without blocking the main thread.
41. What is the purpose of process.nextTick in Node.js?
Answer: process.nextTick schedules a callback function to be invoked in the next iteration of the event loop, before any I/O operations. It's used to handle asynchronous operations at a very high priority.
console.log('Start'); process.nextTick(() => { console.log('Next tick'); }); console.log('End'); // Output: // Start // End // Next tick
42. Explain the cluster module in Node.js.
Answer: The cluster module allows you to create child processes (workers) that share the same server ports. This is useful for taking advantage of multi-core systems and running multiple instances of a Node.js application.
const cluster = require('cluster'); const http = require('http'); const numCPUs = require('os').cpus().length; if (cluster.isMaster) { for (let i = 0; i < numCPUs; i++) { cluster.fork(); } cluster.on('exit', (worker, code, signal) => { console.log(`Worker ${worker.process.pid} died`); }); } else { http.createServer((req, res) => { res.writeHead(200); res.end('Hello, world!\n'); }).listen(8000); }
43. What is the difference between require and import?
Answer:
- require: CommonJS module syntax used in Node.js.
- import: ES6 module syntax used in modern JavaScript (Node.js with ES modules and browsers).
// CommonJS (Node.js) const fs = require('fs'); // ES6 (Browsers and Node.js with ES modules) import fs from 'fs';
44. Explain Object.seal and Object.freeze.
Answer:
- Object.seal: Prevents new properties from being added to an object, but existing properties can still be modified.
- Object.freeze: Prevents new properties from being added and existing properties from being modified or deleted.
let obj = { prop: 42 }; Object.seal(obj); obj.prop = 33; // Allowed delete obj.prop; // Not allowed Object.freeze(obj); obj.prop = 55; // Not allowed
45. What are Set and WeakSet?
Answer:
- Set: A collection of unique values. It can store any type of values.
- WeakSet: Similar to Set, but it only stores objects and does not prevent garbage collection of its items.
let set = new Set([1, 2, 3, 4, 4]); console.log(set); // Set { 1, 2, 3, 4 } let weakSet = new WeakSet(); let obj = {}; weakSet.add(obj); console.log(weakSet.has(obj)); // true
46. What is a Polyfill?
Answer: A polyfill is a piece of code (usually JavaScript on the web) used to provide modern functionality on older browsers that do not natively support it.
if (!Array.prototype.includes) { Array.prototype.includes = function(searchElement, fromIndex) { return this.indexOf(searchElement, fromIndex) !== -1; }; }
47. Explain the use of requestAnimationFrame.
Answer: requestAnimationFrame is used to perform animations in the browser. It tells the browser that you wish to perform an animation and requests that the browser calls a specified function to update an animation before the next repaint.
function animate() { // Update animations console.log('Animating...'); requestAnimationFrame(animate); } requestAnimationFrame(animate);
48. What is a Transpiler?
Answer: A transpiler is a tool that translates code from one language to another. In the context of JavaScript, Babel is a common transpiler that converts ES6+ code into ES5 for compatibility with older browsers.
// ES6+ code const greet = () => { console.log('Hello, world!'); }; // ES5 code after transpilation var greet = function() { console.log('Hello, world!'); };
49. Explain ArrayBuffer and TypedArray.
Answer:
- ArrayBuffer: A generic, fixed-length binary data buffer. It is used to represent a generic, fixed-length raw binary data buffer.
- TypedArray: Provides a view of the data stored in an ArrayBuffer and allows for manipulation of its contents in a type-safe manner.
let buffer = new ArrayBuffer(16); let int32View = new Int32Array(buffer); int32View[0] = 42; console.log(int32View[0]); // 42
50. What is Intl and why is it used?
Answer: The Intl object is used for internationalization and localization, including date and time formatting, number formatting, and string comparison.
let number = 123456.789; console.log(new Intl.NumberFormat('de-DE').format(number)); // "123.456,789" console.log(new Intl.NumberFormat('en-IN').format(number)); // "1,23,456.789"
Conclusion
These advanced JavaScript interview questions and answers will help you prepare thoroughly for your next coding interview. Reviewing these topics will deepen your understanding and ensure you're well-equipped to tackle complex JavaScript problems and concepts. Good luck with your interview preparation!
Comments
Post a Comment