JavaScript is a fundamental skill for any aspiring web developer, and landing a job in this field can be a challenging task, especially for freshers. One of the most crucial steps in the interview process is the technical interview, where your JavaScript skills are put to the test. To help you prepare and boost your confidence, we've compiled a list of the top 50 basic JavaScript interview questions and answers that are commonly asked in interviews.
Hoisting describes the behavior of variable declarations in JavaScript. Declarations using var
are "moved" to the top of their scope during compilation. Only the declaration is hoisted, not the initialization.
Example with var
:
Visualized as:
Variables with let
, const
, and class
:
These are also hoisted but not initialized. Accessing them before declaration results in a ReferenceError
.
Function Expressions:
Only the declaration is hoisted.
Function Declarations:
Both declaration and definition are hoisted.
Import Statements:
Imports are hoisted, making them available throughout the module, with side effects occurring before other code runs.
let
, var
or const
?var
: Function-scoped or globally scoped.let
and const
: Block-scoped (only accessible within the nearest set of curly braces).Example:
var
and let
: Can be declared without an initial value.const
: Must be initialized at the time of declaration.Example:
var
: Allows redeclaration.let
and const
: Do not allow redeclaration.Example:
var
and let
: Allow reassignment.const
: Does not allow reassignment.Example:
var
: Variables are hoisted and initialized to undefined
.let
and const
: Variables are hoisted but not initialized, causing a ReferenceError
if accessed before declaration.Example:
==
and ===
in JavaScript?==
)Examples:
###Strict Equality Operator (===
)
true
.Examples:
Use ==
only when comparing against null
or undefined
for convenience.
Prefer ===
for all other comparisons to avoid pitfalls of type coercion and ensure both value and type are the same.
The event loop is crucial for handling asynchronous operations in JavaScript, allowing single-threaded execution without blocking.
1. Call Stack:
2. Web APIs/Node.js APIs:
setTimeout()
, HTTP requests) on separate threads.3. Task Queue (Macrotask Queue):
setTimeout()
, setInterval()
, and UI events.4. Microtask Queue:
Promise
callbacks).Console Output:
Explanation:
Start
and End
are logged first (synchronous).Promise 1
is logged next (microtask).Timeout 1
and Timeout 2
are logged last (macrotasks).Understanding the event loop helps write efficient, non-blocking JavaScript code.
Event delegation is an efficient way to handle events on multiple child elements by attaching a single event listener to a common parent element. This is useful for managing events on many similar elements, like list items.
event.target
to identify the actual element that triggered the event.A single click listener on <ul>
handles clicks on any <li>
due to event bubbling.
Dynamic Content:
Simplifying Code:
this
works in JavaScriptThe this
keyword in JavaScript can be quite confusing as its value depends on how a function is called. Here are the main rules that determine the value of this
:
new
KeywordCreates a new object and sets this
to that object.
apply
, call
, or bind
Explicitly sets this
to a specified object.
this
is bound to the object the method is called on.
In non-strict mode, defaults to the global object (window
in browsers); in strict mode, defaults to undefined
.
Inherit this
from their lexical enclosing scope.
this
ES2015 introduced arrow functions which capture this
from their lexical scope. This can simplify code but requires caution when integrating with libraries expecting traditional function context.
Example:
sessionStorage
and localStorage
.Cookies, localStorage, and sessionStorage are key client-side storage mechanisms in web applications, each serving distinct purposes:
Purpose: Stores small data pieces sent to the server with HTTP requests.
Capacity: Limited to around 4KB per domain.
Lifespan: Can have expiration dates; session cookies are cleared when the browser closes.
Access: Domain-specific; accessible across pages and subdomains.
Security: Supports HttpOnly and Secure flags to restrict JavaScript access and ensure HTTPS transmission.
Example Usage:
localStorage
Purpose: Stores data persistently on the client-side.
Capacity: Around 5MB per origin.
Lifespan: Data remains until explicitly cleared.
Access: Available across all tabs and windows within the same origin.
Security: All JavaScript on the page can access localStorage values.
Example Usage:
sessionStorage
Purpose: Stores session-specific data that persists until the browser or tab is closed.
Capacity: Similar to localStorage, around 5MB per origin.
Lifespan: Cleared when the tab or browser closes; reloading the page retains data.
Access: Limited to the current tab or window.
Security: All JavaScript on the page can access sessionStorage values.
Example Usage:
<script>
, <script async>
and <script defer>
<script>
TagThe <script>
tag is used to include JavaScript in a web page. When used without async
or defer
attributes:
Example:
<script async>
TagExample:
<script defer>
Tag:
DOMContentLoaded
.Example:
null
, undefined
or undeclared?Undeclared: A variable that is not declared using var
, let
, or const
will be created globally and can cause errors. Avoid them by using try/catch
blocks to detect them.
undefined
: A declared variable without an assigned value is undefined
. Use ===
or typeof
to check for undefined
. Note that ==
will also return true
for null
.
null
: A variable explicitly assigned null
represents no value. Use ===
to check for null
. Don't use ==
as it will also return true
for undefined
.
Best Practices:
null
to variables if you don't intend to use them yet..call
and .apply
in JavaScript?.call
and .appl
are used to invoke functions, setting this
within the function. The difference lies in how they handle arguments:
Memory Aid:
Example:
Function.prototype.bind
Function.prototype.bind
creates a new function with a specific this
context and optionally preset arguments. It's useful for maintaining the correct this
value in methods passed to other functions.
Example:
Its main purposes are:
this
to preserve context: The primary function of bind
is to attach the this
value of a function to a specific object. When you use func.bind(thisArg)
, it generates a new function with the same code as func
, but with this
permanently set to thisArg
.bind
also enables you to pre-set arguments for the new function. Any arguments provided to bind
after thisArg
will be prepended to the argument list when the new function is invoked.bind
allows you to borrow methods from one object and use them on another object, even if the methods were not initially designed for that object.The advantage of using the arrow syntax for a method in a constructor is that it automatically binds the this
value to the constructor's this
context. This means that when the method is called, it will always refer to the constructor's this
context, rather than the global scope or some other unexpected context.
In traditional function expressions, the this
value is determined by how the function is called, which can lead to unexpected behavior if not properly bound. By using an arrow function, you can ensure that the this
value is always bound to the constructor's this
context, making your code more predictable and easier to maintain.
For example, in the code snippet:
The sayName1
method uses a traditional function expression, which means its this
value is determined by how it's called. If you call john.sayName1.call(dave)
, the this
value will be dave
, and the method will log Dave
to the console.
On the other hand, the sayName2
method uses an arrow function, which means its this
value is automatically bound to the constructor's this
context. If you call john.sayName2.call(dave)
, the this
value will still be john
, and the method will log John
to the console.
This can be particularly helpful in React class components, where you often need to pass methods as props to child components. By using arrow functions, you can ensure that the methods always refer to the correct this
context, without having to manually bind this
in the constructor.
Prototypical inheritance allows objects to inherit properties and methods from other objects using a prototype-based model.
Object.getPrototypeOf()
and Object.setPrototypeOf()
.JavaScript looks for properties/methods on the object, then its prototype, and so on up the chain until null
.
Functions used with new
to create objects, setting their prototype to the constructor's prototype
.
Object.create()
Creates a new object with a specified prototype.
function Person(){}
, const person = Person()
, and const person = new Person()
?function Person(){}
is a standard function declaration in JavaScript. When written in PascalCase, it follows the convention for functions intended to be used as constructors.
const person = Person()
simply calls the function and executes its code. If no return value is specified, person
will be undefined
. This is not a constructor call and does not create a new object.
const person = new Person()
creates a new object using the Person
constructor function. The new
keyword creates a new object and sets its prototype to Person.prototype
. The this
keyword inside the constructor function refers to the new object being created.
foo
between function foo() {}
and var foo = function() {}
Syntax: function foo() {}
Description: Defines a named function that can be called throughout the enclosing scope.
Example:
Syntax: var foo = function() {}
Description: Defines a function and assigns it to a variable, often used in specific contexts.
Example:
Hoisting:
Function Declarations: The entire function is hoisted; can be called before its definition.
Function Expressions: Only the variable is hoisted, not the function body; calling it before definition results in an error.
Name Scope:
Function Expressions: These can be named internally, but the name is only accessible within the function.
Function Declarations:
Function Expressions:
Here are the various ways to create objects in JavaScript:
Object Literals ({}
): Simplest way to create objects using key-value pairs within curly braces.
Object() Constructor: Using the new
keyword with the built-in Object
constructor to create an object.
Object.create() Method: Creating a new object using an existing object as a prototype.
ES2015 Classes: Defining a blueprint for objects using classes, similar to other programming languages.
Constructor Functions: Reusable blueprints for objects, using the new
keyword to create instances.
Note: Constructor functions are less commonly used now that ES2015 classes are widely supported.
A higher-order function is a function that:
Takes another function as an argument: A function that accepts another function as a parameter.
Returns a function as its result: A function that returns another function as its output.
In other words, a higher-order function is a function that operates on other functions, either by taking them as input or by producing them as output.
Uses function constructors and prototypes.
Example:
Uses the class
syntax, making code more readable and adding features.
Example:
class
keyword, more concise and easier to understandstatic
keywordObject.create()
and manual prototype chain settingextends
keyword, simpler and more intuitivesuper
keyword to call parent class's constructor and methodsEvent bubbling is a mechanism in the DOM (Document Object Model) where an event, such as a click, is first triggered on the target element and then propagates upward through the DOM tree to the root of the document.
Bubbling Phase:
Description: During the bubbling phase, the event starts at the target element and bubbles up through its ancestors in the DOM hierarchy. Event handlers attached to the target element and its ancestors can all potentially receive and respond to the event.
Example:
When you click the Click me!
button, both the child and parent event handlers will be triggered due to event bubbling.
Stopping Event Bubbling:
Method: Use stopPropagation()
to stop the event from bubbling up the DOM tree.
Example:
Event capturing is a propagation mechanism in the DOM where an event, such as a click, is first triggered at the root of the document and then flows down through the DOM tree to the target element.
Event Propagation Phases:
Enabling Event Capturing:
{ capture: true }
as the third argument to addEventListener()
.Example:
When you click the Click me!
button, the parent element's capturing handler will be triggered before the child element's handler.
Stopping Propagation:
Use stopPropagation()
to prevent the event from traveling further down the DOM tree during the capturing phase.
Example:
In this example, only the parent event listener will be called when you click the "Click me!" button, as the event propagation is stopped at the parent element.
mouseenter
and mouseover
event in JavaScript and browsers?mouseenter
mouseover
Example:
Example:
AJAX is a set of web development techniques using various web technologies on the client side to create asynchronous web applications. Unlike traditional web applications where each user interaction triggers a full page reload, AJAX allows web applications to send data to and retrieve data from a server asynchronously without interfering with the display and behavior of the existing page. This enables dynamic updates to the web page without the need to reload it.
Key Points:
XMLHttpRequest
, but fetch()
is now preferred for modern web applications.XMLHttpRequest
APIExample:
XMLHttpRequest
, sets up a callback function to handle state changes, opens a request to a URL, and sends the request.fetch()
APIExample:
.then()
to parse JSON data, and manages errors with .catch()
.fetch
fetch()
initiates an asynchronous request to fetch a resource from a URL.
Example:
fetch()
returns a Promise that resolves to a Response
object representing the server's response.The Response
object offers methods to handle the body content, such as .json()
, .text()
, .blob()
.
Example:
fetch()
is asynchronous, allowing the browser to continue executing other tasks while waiting for the server response..then()
, .catch()
) are handled in the microtask queue as part of the event loop.fetch()
configures various request aspects, such as HTTP method, headers, body, credentials, and caching..catch()
or try/catch
with async/await
.AJAX (Asynchronous JavaScript and XML) enables web pages to send and retrieve data asynchronously, allowing for dynamic updates without full page reloads.
XMLHttpRequest
and fetch()
?Both XMLHttpRequest (XHR)
and fetch()
enable asynchronous HTTP requests in JavaScript, but differ in syntax, handling, and features.
setRequestHeader
method.send
method.body
property in the options parameter.responseType
to handle different formats..then
for accessing data.onerror
event..catch
method.abort()
method.AbortController
for request cancellation.onprogress
event.Choosing Between Them: fetch()
is generally preferred due to its cleaner syntax and promise-based handling, but XMLHttpRequest
may still be useful for specific cases like progress tracking.
JavaScript has various data types categorized into two groups: primitive and non-primitive (reference) types.
true
or false
.Determining Data Types: JavaScript is dynamically typed, meaning variables can hold different data types over time. Use the typeof
operator to determine a variable's type.
Iterating over object properties and arrays is very common in JavaScript and we have various ways to achieve this. Here are some of the ways to do it:
for...in
StatementLoops over all enumerable properties of an object, including inherited ones.
Object.keys()
Returns an array of an object's own enumerable property names.
Object.entries()
Returns an array of a given object's own enumerable string-keyed property [key, value] pairs.
Object.getOwnPropertyNames()
Returns an array of all properties (including non-enumerable ones) found directly upon a given object.
for
LoopTraditional loop over array elements.
Array.prototype.forEach()
Executes a provided function once for each array element.
for...of
StatementLoops over iterable objects like arrays.
Array.prototype.entries()
Provides both the index and value of each array element in a for...of
loop.
Introduced in ES2015, the spread syntax (...
) is useful for copying and merging arrays and objects without modifying the originals. It's commonly used in functional programming, Redux, and RxJS.
Copying Arrays/Objects: Creates shallow copies.
Merging Arrays/Objects: Merges them into a new one.
Function Arguments: Passes array elements as individual arguments.
Array vs. Object Spreads: Only iterables can be spread into arrays; arrays can be spread into objects.
The rest syntax (...
) gathers multiple elements into an array or object, the inverse of the spread syntax.
Function Parameters: Collects remaining arguments into an array.
Array Destructuring: Collects remaining elements into a new array.
Object Destructuring: Collects remaining properties into a new object.
Rest Parameter Rules: Must be the last parameter.
Map
object and a plain object in JavaScript?size
property to get the number of key-value pairs.forEach
, keys()
, values()
, and entries()
.Object.keys()
, Object.values()
, or Object.entries()
for iteration.Map
/Set
vs WeakMap
/WeakSet
?The main distinctions between Map
/Set
and WeakMap
/WeakSet
in JavaScript are as follows:
Map
and Set
accept keys of any type (objects, primitive values), whereas WeakMap
and WeakSet
exclusively use objects as keys, excluding primitive values like strings or numbers.Map
and Set
retain strong references to their keys and values, preventing their disposal by garbage collection. In contrast, WeakMap
and WeakSet
employ weak references for keys (objects), allowing these objects to be collected by garbage collection if no other strong references persist.Map
and Set
are enumerable and can be iterated over, while those in WeakMap
and WeakSet
are non-enumerable, precluding retrieval of key or value lists directly from them.Map
and Set
possess a size
property that indicates the number of elements they contain. In contrast, WeakMap
and WeakSet
lack a size
property because their size may vary as a result of garbage collection.Map
and Set
serve well as general-purpose data structures and for caching purposes. Conversely, WeakMap
and WeakSet
are primarily suited for storing metadata or additional object-related data without impeding the object's potential garbage collection when no longer needed.One practical use case for the arrow function syntax in JavaScript is simplifying callback functions, particularly in scenarios where you need concise, inline function definitions. Here's an example:
Use Case: Mapping an Array
Suppose you have an array of numbers and you want to double each number using the map
function.
Using arrow function syntax, you can achieve the same result more succinctly:
In asynchronous programming, a callback function is passed as an argument to another function and invoked when a task completes, such as fetching data or handling I/O operations. Here's a concise explanation:
Debouncing delays function execution until a specified time has passed since its last call, useful for tasks like search input handling.
Throttling limits function execution to at most once within a specified interval, beneficial for tasks like handling frequent events such as window resizing or scrolling.
These techniques optimize performance and manage event-driven behaviors effectively in JavaScript applications.
Destructuring assignment simplifies extracting values from arrays or properties from objects into separate variables:
This syntax uses square brackets for arrays and curly braces for objects, enabling concise variable assignment directly from data structures.
Hoisting moves function declarations to the top of their scope during compilation, allowing them to be called before their actual placement in the code. Function expressions and arrow functions, however, must be defined before they are called to avoid errors.
In ES2015, classes use extends
to enable one class to inherit properties and methods from another. The super
keyword accesses the parent class's constructor and methods.
Here, Dog
inherits from Animal
, showcasing how classes streamline inheritance and method overriding in JavaScript.
Lexical scoping in JavaScript determines variable access based on its position in the source code. Nested functions can access variables from their outer scope.
Here, innerFunction
can access outerVariable
due to lexical scoping rules.
Scope in JavaScript determines the visibility of variables and functions within different parts of the code. There are three main types: global scope, function scope, and block scope.
Global scope variables are accessible throughout the code, while function scope variables are limited to the function they are declared in. Block scope, introduced in ES6, confines variables to the block they are declared within (e.g., within curly braces ).
The spread operator (...) in JavaScript expands elements of an iterable (like arrays or objects) into individual elements. It's used for copying arrays or objects, merging them, and passing array elements as function arguments.
The spread operator simplifies tasks like copying, merging, and function argument handling by expanding iterable elements into individual components.
this
binding in event handlersIn JavaScript, the this
keyword refers to the object executing the current code. In event handlers, this
usually points to the element that triggered the event. However, its value can vary based on how the handler is defined and invoked. To ensure this
refers correctly, methods like bind()
, arrow functions, or explicit context assignment are used.
These approaches help maintain the intended context for this
within event handling functions, ensuring predictable behavior across different event-triggering scenarios in JavaScript applications.
Classical Inheritance: In languages like Java and C++, classes inherit from other classes through a hierarchical structure. Instances are created from classes using constructors.
Prototypal Inheritance: In JavaScript, objects inherit directly from other objects. Objects serve as prototypes, and new objects are created based on existing ones.
Classical inheritance uses classes for instantiation, while prototypal inheritance leverages object linkage for property and behavior inheritance, highlighting JavaScript's unique approach to object-oriented programming.
document.querySelector()
and document.getElementById()
document.querySelector()
selects elements using CSS selectors and returns the first match.
document.getElementById()
selects an element by its ID attribute and returns the element with that specific ID.
While document.querySelector()
offers flexibility with CSS selectors, document.getElementById()
is straightforward for selecting elements by their unique IDs in the DOM.
Dot Notation: Concise and straightforward, it accesses object properties using valid identifiers.
Bracket Notation: Flexible, it accesses properties using strings, suitable for names with special characters or dynamic properties.
Dot notation is clear for standard properties, while bracket notation handles special cases like dynamic or non-standard property names effectively.
Accessible from anywhere in the code.
Limited to the function where it's declared.
Restricted to the block where let
or const
is used.
These scopes define where variables can be accessed, from global access throughout the code to specific function or block-level access for better control and encapsulation of variables.
Duplicates top-level properties; nested objects remain referenced.
Duplicates all levels, creating independent nested objects.
Shallow copies share references to nested objects, while deep copies create entirely new instances, ensuring independent modifications.
var
, let
, and const
var
:
let
and const
:
const
:
Closures in JavaScript provide a mechanism to create private variables by encapsulating them within a function scope. Here's how closures can be used to achieve this:
Set
s and Map
s handle equality checks for objects?Set
s and Map
s in JavaScript determine the equality of objects based on reference equality, not by comparing their contents. This means objects are considered equal only if they point to the same memory location. For instance:
In this example, obj1
and obj2
are treated as separate entries in the Set because they are distinct objects, despite having identical properties. Therefore, Sets and Maps rely on object references to determine equality, not their internal values.
To access the index of an element in an array during iteration, you can utilize methods like forEach, map, for...of with entries, or a traditional for loop. Here's an example using forEach:
To determine the type of a variable in JavaScript, you use typeof
followed by the variable name. It returns a string indicating the variable's type: "string", "number", "boolean", "object", "function", "undefined", or "symbol". For arrays, use Array.isArray(variableName)
, and for null, check variableName === null
.
You've made it to the end of our extensive list of JavaScript interview questions and answers! We hope this guide has helped you gain the confidence and skills you need to ace your next JavaScript interview. Remember, practice is key, so keep coding and reviewing the concepts until they become second nature.