Intermediate Senior Full-Stack Developer Interview Questions

Table Of Contents
- What is the best way to remove duplicates from an array in ES6?
- What are connection leaks in Java, and how can they be fixed?
- What is multi-threading, and why is it used?
- What is “Strict Mode” in JavaScript, and how do you use it?
- How do you handle browser compatibility issues?
- How do you optimize SQL queries?
- What is the difference between an abstract class and an interface in Java?
- How does DevOps work?
- What is the difference between JDBC and Hibernate?
- What is a deadlock in Java, and how do you avoid it?
- What is the purpose of the Service Worker in a Progressive Web App (PWA)?
- What is the difference between synchronous and asynchronous programming in JavaScript?
As a Full-Stack Developer eyeing an intermediate or senior role, you know that interviews at this level are rigorous, challenging both your technical depth and strategic thinking. Interviewers don’t just want code wizards; they seek developers who can bridge the gap between frontend elegance and backend robustness. In this guide, I’ll take you through key areas you’re likely to encounter in these interviews: from JavaScript frameworks like React and Angular, to backend essentials in Node.js or Java, to complex database structures, API integrations, and cloud service architectures. You’ll see exactly how these questions are designed to test not only your coding abilities but your problem-solving approach, design choices, and scalability tactics.
This isn’t just a list of questions; it’s a roadmap to sharpen your skills and get you ready to lead as a Full-Stack Developer. Through targeted examples and thoughtful explanations, this guide will help you tackle interview questions with confidence, demonstrating both your technical expertise and your ability to think critically about system architecture and best practices. By mastering these concepts, you’ll walk into your next interview ready to stand out and showcase why you’re an invaluable asset for any team.
1. What is the best way to remove duplicates from an array in ES6?
In my experience, the best way to remove duplicates from an array in ES6 is by using the Set
object combined with the spread operator (...
). A Set
automatically removes duplicate values because it only stores unique elements. By converting an array into a Set
, we eliminate duplicates, and then we can convert it back into an array using the spread operator. This approach is efficient and concise, making it an ideal solution in ES6.
Here’s a code snippet:
const arrayWithDuplicates = [1, 2, 3, 4, 3, 2, 1];
const uniqueArray = [...new Set(arrayWithDuplicates)];
console.log(uniqueArray); // Output: [1, 2, 3, 4]
To explain, new Set(arrayWithDuplicates)
creates a Set
containing only unique elements from arrayWithDuplicates
. The spread operator ...
then takes each unique element from the Set
and places it back into an array. This approach is concise, readable, and leverages ES6 features effectively.
See also: Scenario Based Java Interview Questions
2. What are connection leaks in Java, and how can they be fixed?
Connection leaks in Java occur when database connections are not closed after being used, leading to resource exhaustion and poor application performance. In my experience, connection leaks often result from forgetting to close connections, particularly in long-running applications. Over time, open connections accumulate, which may cause the database to refuse new connections.
To fix connection leaks, I ensure that all database connections are closed properly. One best practice is using the try-with-resources
statement introduced in Java 7, which automatically closes resources when they’re no longer needed. Here’s how it works:
try (Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement()) {
// Execute queries and process data
} catch (SQLException e) {
e.printStackTrace();
}
In this example, the try-with-resources
statement ensures that the connection
and statement
are automatically closed, even if an exception occurs. This approach minimizes the risk of connection leaks and is especially useful for database-related code.
See also: Java Interview Questions for 10 years
3. What is multi-threading, and why is it used?
In my experience, multi-threading is a powerful technique that allows an application to run multiple threads (smaller units of a process) simultaneously. Each thread can perform tasks independently, which improves the efficiency and responsiveness of the application. Multi-threading is widely used for tasks like handling concurrent requests, parallel processing, and background tasks.
The main reason multi-threading is used is to make better use of CPU resources, especially in tasks that can run in parallel. For example, in a server application, multi-threading allows it to handle multiple client requests at the same time, enhancing user experience and improving system throughput. However, managing threads requires careful synchronization to avoid issues like race conditions and deadlocks, as multiple threads can access shared resources simultaneously.
Here’s a basic example of multi-threading in Java using the Thread
class:
class MyThread extends Thread {
public void run() {
System.out.println("Thread is running...");
}
}
public class Main {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
}
In this example, MyThread
is a class extending Thread
, and the run
method contains the code to be executed by the thread. When thread.start()
is called, a new thread begins executing the code inside run
. This parallel execution allows applications to handle multiple tasks more efficiently, improving overall performance.
See also: Accenture Java interview Questions
4. What is “Strict Mode” in JavaScript, and how do you use it?
“Strict Mode” in JavaScript is a way to enforce stricter parsing and error handling in your code. In my experience, it helps me avoid common mistakes by catching errors that might go unnoticed in non-strict mode. For instance, strict mode prevents the use of undeclared variables, assignment to non-writable properties, and deletion of variables that shouldn’t be deleted. I find it useful because it encourages cleaner, more reliable code.
To enable strict mode, I simply add "use strict";
at the beginning of a JavaScript file or function:
"use strict";
function example() {
undeclaredVar = 10; // Throws an error in strict mode
}
example();
In this example, strict mode causes an error because undeclaredVar
is not declared with let
, const
, or var
. Without strict mode, this mistake would go unnoticed, potentially causing issues later in the code. I recommend using strict mode in most cases as it promotes best practices.
See also: Accenture Angular JS interview Questions
5. How do you prevent a bot from scraping a public API?
To prevent a bot from scraping a public API, I would implement several strategies that make it harder for automated tools to access data without permission. In my experience, rate limiting is one of the most effective methods. It restricts the number of API requests allowed from a specific IP address over a given period, making it challenging for bots to send frequent requests. Another useful strategy is using API keys and access tokens, which only allow authenticated users to access the API.
Here’s an example of how rate limiting might be implemented in an Express.js application:
const express = require("express");
const rateLimit = require("express-rate-limit");
const app = express();
// Set up rate limiting
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
message: "Too many requests, please try again later."
});
// Apply the rate limiter to all requests
app.use("/api", limiter);
app.get("/api/data", (req, res) => {
res.send("Data served.");
});
app.listen(3000, () => {
console.log("Server running on port 3000");
});
In this example, express-rate-limit
is used to cap requests at 100 per IP every 15 minutes. If a client exceeds this limit, they’ll receive a message asking them to try again later. Rate limiting, alongside authentication and CAPTCHAs, helps protect public APIs by restricting the frequency and access of bots.
6. How do you handle browser compatibility issues?
In my experience, browser compatibility issues arise when different browsers interpret code slightly differently. To handle these issues effectively, I usually start by testing the application on multiple browsers, such as Chrome, Firefox, Safari, and Edge, to identify specific areas that aren’t functioning as expected. One of my go-to strategies is to use CSS resets and normalize CSS files, which ensure that all elements render more consistently across browsers. Additionally, I use feature detection instead of browser detection, which allows me to check if a browser supports certain features before implementing them.
When writing JavaScript, I rely on polyfills to add support for features not natively available in older browsers. For example, I use the Babel library to transpile my ES6 code into ES5, which has broader support. Here’s an example of how Babel can help:
// Original ES6 code
const greet = () => console.log("Hello!");
// Transpiled ES5 code with Babel
var greet = function() {
console.log("Hello!");
};
By transpiling ES6 code into ES5, I ensure that older browsers, which might not support arrow functions, can still run the script. This approach helps me maintain compatibility without compromising on modern coding practices.
See also: Collections in Java interview Questions
7. What is a Pascal string?
In programming, a Pascal string is a string format that includes a length byte at the beginning, which indicates the number of characters in the string. This is different from a C-style string, which uses a null character to mark the end of the string. In my experience, Pascal strings are useful in specific contexts, like certain networking protocols or file formats, where knowing the string length in advance is necessary.
Here’s a simple example to illustrate how Pascal strings work:
// Pascal string representation in JavaScript
function toPascalString(str) {
const length = str.length;
return String.fromCharCode(length) + str;
}
const pascalStr = toPascalString("Hello");
console.log(pascalStr); // Outputs a string with the length byte at the start
In this code, toPascalString
prepends the string’s length as a single byte, mimicking the Pascal string structure. The first byte (String.fromCharCode(length)
) denotes the string length, and the rest is the actual string content. Pascal strings are less common in web development but can be valuable in low-level programming tasks.
See also: Intermediate AI Interview Questions and Answers
8. What steps will you take to reduce the load time of a web application?
Reducing the load time of a web application is crucial for user experience and SEO. In my experience, one of the best ways to achieve this is by minifying CSS, JavaScript, and HTML files, which reduces their size and speeds up loading. Additionally, I use lazy loading for images and other media, ensuring that they load only when visible to the user, reducing the initial load time.
I also optimize JavaScript and CSS delivery by placing scripts at the bottom of the page or using the async
and defer
attributes for non-critical scripts. Here’s a simple example of how to use these attributes:
<!-- Async loads script as soon as it’s available -->
<script async src="script.js"></script>
<!-- Defer loads script after the HTML document is fully parsed -->
<script defer src="another-script.js"></script>
Using async
and defer
prevents scripts from blocking page rendering, improving load speed. I also leverage caching and content delivery networks (CDNs) to ensure assets are loaded from a location closer to the user, further enhancing performance.
See also: Full Stack developer Interview Questions
9. What are semantic HTML tags, and why should you use them?
Semantic HTML tags are HTML elements that clearly describe their purpose, helping both developers and browsers understand the structure of the content. Tags like <header>
, <footer>
, <article>
, and <section>
are examples of semantic tags. In my experience, using these tags makes my code more readable and accessible, and it improves the search engine optimization (SEO) of the application, as search engines use semantic tags to better understand the content.
For example, here’s how I might structure a basic web page with semantic HTML:
<header>
<h1>My Website</h1>
</header>
<main>
<article>
<h2>Article Title</h2>
<p>Article content goes here.</p>
</article>
</main>
<footer>
<p>Contact us at email@example.com</p>
</footer>
In this example, <header>
and <footer>
define the header and footer sections, while <main>
and <article>
indicate the primary content areas. This structure not only improves readability but also assists screen readers and search engines in interpreting the content’s purpose more effectively.
10. What is the event loop in JavaScript?
The event loop is a core concept in JavaScript that enables non-blocking, asynchronous operations. In my experience, understanding the event loop is essential for writing efficient JavaScript code. JavaScript runs in a single-threaded environment, which means only one task can be executed at a time. However, the event loop allows JavaScript to manage asynchronous tasks by pushing them to the call stack only when they’re ready to execute.
Here’s a basic example that shows how the event loop handles asynchronous tasks:
console.log("Start");
setTimeout(() => {
console.log("Inside setTimeout");
}, 0);
console.log("End");
In this code, setTimeout
is an asynchronous function, so it’s sent to the callback queue after a delay of 0 milliseconds. The event loop checks the callback queue after the main stack is empty (i.e., after “Start” and “End” are logged) and then executes the callback. This mechanism allows JavaScript to handle multiple tasks without blocking the main thread, improving performance and responsiveness.
See also: Java interview questions for 10 years
11. What is the main difference between Promises and async/await in JavaScript?
In JavaScript, Promises and async/await are both used to handle asynchronous operations, but they differ in syntax and ease of use. A Promise represents a value that will be available in the future, and it allows us to handle asynchronous tasks with .then()
and .catch()
methods. However, chaining multiple .then()
statements can sometimes make the code harder to read.
With async/await, we can write asynchronous code that looks and behaves more like synchronous code, which improves readability. Using await
pauses the execution until the Promise is resolved, making it feel more intuitive. Here’s an example comparing the two approaches:
// Using Promises
fetchData()
.then(response => processResponse(response))
.catch(error => handleError(error));
// Using async/await
async function fetchAndProcess() {
try {
const response = await fetchData();
processResponse(response);
} catch (error) {
handleError(error);
}
}
In this example, async/await
simplifies the flow, making it clearer to read and understand, especially in complex scenarios.
12. What are filters in Vue.js?
Filters in Vue.js are a convenient way to format data that will be displayed in the template. They don’t alter the actual data but allow me to present it differently based on specific needs, like formatting dates or capitalizing text. In my experience, filters help keep templates clean and readable by handling minor data transformations directly within the template syntax.
For example, if I want to capitalize text, I can define a filter like this:
// Defining a filter to capitalize text
Vue.filter("capitalize", function(value) {
if (!value) return "";
return value.charAt(0).toUpperCase() + value.slice(1);
});
// Using the filter in a Vue template
<p>{{ message | capitalize }}</p>
This capitalize
filter modifies text within the template, applying the change only when displayed, without altering the underlying data.
See also: Salesforce Admin Interview Questions for Beginners
13. How do you optimize SQL queries?
To optimize SQL queries, I start by analyzing the query execution plan, which helps me understand how the database processes the query. In my experience, one of the most effective ways to improve performance is by creating indexes on columns that are frequently used in WHERE
clauses. This allows the database to quickly locate rows, reducing query time significantly.
Another useful technique is to avoid using SELECT *
and only select the columns I actually need. Additionally, I break down complex queries with multiple joins into smaller queries or use subqueries only when necessary, as they can sometimes slow down performance. Here’s an example:
-- Adding an index to a frequently used column
CREATE INDEX idx_customer_name ON customers (name);
-- Optimized query with specific columns
SELECT order_id, order_date FROM orders WHERE customer_id = 1;
By selecting only specific columns (order_id
and order_date
), I reduce the data load, which can improve query efficiency, especially for large datasets.
14. What is the main difference between a web server and an application server?
A web server primarily handles HTTP requests and serves static content like HTML, CSS, and JavaScript files. In contrast, an application server is designed to handle dynamic content, including business logic and database interactions. In my experience, web servers are lighter and faster at delivering static files, while application servers are more robust and can handle complex operations such as authentication and authorization.
For example, a web server like Nginx or Apache is ideal for serving static websites, whereas an application server like Tomcat or Node.js can process backend logic and interact with databases. Many modern setups combine both, using a web server for static content and an application server for dynamic processes to enhance performance and scalability.
15. What are the advantages of pair programming?
In my experience, pair programming offers several advantages, including improved code quality, faster problem-solving, and knowledge sharing. With one person writing code (the “driver”) and the other reviewing and suggesting improvements (the “observer” or “navigator”), we can catch mistakes early and think critically about design choices.
Pair programming also promotes continuous learning because developers can share different perspectives, techniques, and best practices. This collaborative approach helps build stronger coding skills, fosters team bonding, and makes troubleshooting more efficient, ultimately leading to better quality code and fewer bugs.
See also: Java interview questions for 10 years
16. Why and how do you clear floats in CSS?
When using floats in CSS to position elements, surrounding elements may not automatically adjust, which can disrupt the layout. To fix this, I use clearing techniques to ensure that parent elements contain their floated children. One of my preferred methods is to apply a clearfix
class to the parent element, which forces it to wrap around its floated children.
Here’s an example of a CSS clearfix:
.clearfix::after {
content: "";
display: table;
clear: both;
}
In this code, the .clearfix
class is applied to a parent container with floated children. The ::after
pseudo-element with clear: both;
clears any floats, ensuring the container wraps around the floated elements. This method is simple and effective for handling floats without altering the HTML structure.
See also: React Redux Interview Questions And Answers
17. What is the difference between an abstract class and an interface in Java?
In Java, an abstract class can have both implemented and unimplemented methods (abstract methods), making it ideal when I need some shared behavior and a common base. On the other hand, an interface only allows for unimplemented methods until Java 8, where default methods were introduced. In my experience, I choose an abstract class when there’s a need for shared code among related classes, and an interface for setting up a contract without shared implementation.
Here’s a simple example showing an abstract class and an interface:
abstract class Animal {
abstract void sound();
void sleep() {
System.out.println("Sleeping...");
}
}
interface Pet {
void play();
}
In this example, the abstract class Animal
has an implemented method sleep()
, and any subclass can use this method. The Pet
interface only defines a contract without shared code.
18. How does database indexing work?
Database indexing improves the speed of data retrieval by creating a data structure (usually a B-tree or hash table) that allows for quicker lookups. When I create an index on a column, the database can use this structure to find rows faster than scanning the entire table. However, indexes come with a trade-off since they consume storage space and may slow down write operations.
For example, I use indexes on columns frequently used in WHERE
clauses or joins to improve query performance. Here’s a basic SQL statement to create an index:
-- Creating an index to speed up lookups on the 'name' column
CREATE INDEX idx_customer_name ON customers (name);
This code creates an index on the name
column in the customers
table. With this index in place, the database can quickly locate rows based on name
, reducing query time, especially in large tables.
See also: Infosys React JS Interview Questions
19. How do you create a callback in JavaScript?
In JavaScript, a callback is a function passed as an argument to another function, allowing it to be called after a certain task is completed. In my experience, callbacks are useful for handling asynchronous operations, such as data fetching, where actions need to wait for data to be ready.
Here’s an example of using a callback function:
function fetchData(callback) {
setTimeout(() => {
console.log("Data fetched");
callback();
}, 1000);
}
fetchData(() => console.log("Callback executed"));
In this example, fetchData
takes a callback, and after the data is “fetched,” the callback runs. This allows the function to control execution flow based on async tasks.
See also: Salesforce Pardot Interview Questions
20. How does DevOps work?
DevOps is a methodology that combines development and operations teams to improve collaboration, automate processes, and speed up software delivery. In my experience, DevOps practices streamline the software development lifecycle by implementing continuous integration (CI) and continuous deployment (CD), where code changes are automatically tested, merged, and deployed. This reduces bottlenecks and enables teams to release updates faster and more reliably.
A DevOps pipeline typically includes version control, automated testing, and monitoring, allowing teams to catch issues early and ensure smooth deployments. Tools like Jenkins, Docker, and Kubernetes are commonly used to build, test, and deploy applications in a consistent environment. This approach fosters a culture of collaboration, where developers and operations work closely to achieve seamless, automated workflows that improve product quality and delivery speed.
21. What is the difference between Map and WeakMap in JavaScript?
In JavaScript, both Map and WeakMap allow us to store key-value pairs, but they have distinct differences. A Map holds key-value pairs and allows any type of key. It also prevents garbage collection, meaning it holds keys until they’re explicitly removed. In contrast, WeakMap only accepts objects as keys and allows for automatic garbage collection. If no references exist to a key in a WeakMap, it is eligible for garbage collection, which helps manage memory efficiently in certain cases.
let map = new Map();
let weakMap = new WeakMap();
let obj = {};
map.set(obj, "Map Value");
weakMap.set(obj, "WeakMap Value");
// Removing the only reference to the object
obj = null;
// Map keeps the object key, WeakMap allows it to be garbage collected
The garbage collection feature of WeakMap makes it ideal for temporary data storage tied to specific objects without preventing memory cleanup.
See also: Salesforce Javascript Developer 1 Practice Exam Questions
22. What are the popular methods of session management in a servlet?
In servlets, session management is essential for keeping track of user activities across multiple requests. Common session management methods include HTTP sessions, cookies, and URL rewriting. HTTP sessions are widely used, where a session ID is generated for each user and stored on the server. Cookies can store user data client-side, though they’re limited in size and may have security concerns. URL rewriting appends session information to the URL, useful if cookies are disabled in the browser.
// Example of starting a session in a servlet
HttpSession session = request.getSession();
session.setAttribute("user", "JohnDoe");
In my experience, using HTTP sessions provides a balanced approach between security and functionality, especially when paired with cookies for cross-request persistence.
23. What is the Zip() function in Python?
The zip() function in Python combines multiple iterables (like lists or tuples) into a single iterable of tuples, where each tuple contains elements from each iterable at the same index. I use zip()
frequently to iterate over pairs of elements from two lists, making data processing efficient.
# Using zip() to combine two lists
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
combined = list(zip(names, ages))
print(combined) # Output: [('Alice', 25), ('Bob', 30), ('Charlie', 35)]
In this example, zip()
creates tuples that combine each name with its respective age, which is especially useful when working with paired data.
See also: Deloitte Salesforce Developer Interview Questions
24.How would you handle multiple asynchronous operations in Node.js and ensure that errors are caught and managed properly in both Promises and async/await syntax? Demonstrate with a code example.
In Node.js, handling multiple asynchronous operations effectively is essential for managing dependencies and catching errors efficiently. Using Promises and async/await, you can control asynchronous flows and manage error handling in different ways. Let’s explore how you’d handle multiple async tasks and capture errors.
With Promises, we often use Promise.all()
to run tasks concurrently. This approach waits for all Promises to resolve or rejects if any one of them fails. Here’s an example of how I’d use Promise.all()
with error handling:
const fetchData1 = () => Promise.resolve('Data from API 1');
const fetchData2 = () => Promise.reject('API 2 failed');
const fetchData3 = () => Promise.resolve('Data from API 3');
Promise.all([fetchData1(), fetchData2(), fetchData3()])
.then((results) => {
console.log('All data:', results);
})
.catch((error) => {
console.error('Error fetching data:', error); // This catches any error in the Promise array
});
In this Promise-based example, if any Promise fails, it goes to the catch
block, handling the error gracefully.
With async/await, I can achieve similar functionality while writing code that feels more synchronous and readable. Here’s an example where I use try-catch
to manage errors for each asynchronous call individually and handle them gracefully.
const fetchData = async () => {
try {
const data1 = await fetchData1();
const data2 = await fetchData2(); // This will throw an error
const data3 = await fetchData3();
console.log('All data:', data1, data2, data3);
} catch (error) {
console.error('Error occurred:', error); // Handles the first error encountered
}
};
fetchData();
In this async/await example, the try-catch
block around my code allows me to handle errors in a more controlled way. If fetchData2
fails, the function stops execution and moves to the catch
block.
25. What is the purpose of the <main> element in HTML?
The <main>
element in HTML represents the main content of a document. It is typically used to wrap the primary content that is unique to the page, excluding headers, footers, and sidebars. Using <main>
enhances accessibility, as screen readers can jump directly to the main content, and it improves search engine optimization (SEO) by defining the main content clearly.
<main>
<h1>About Us</h1>
<p>Welcome to our company website. We specialize in web development.</p>
</main>
By encapsulating the central content within <main>
, I make the structure of the page more semantic and accessible for users and search engines alike.
See also: How to Optimize General Ledger Management in Salesforce?
26. What is a Data Structure, and what are the different types?
A data structure is a specialized way to organize and store data for efficient access and modification. Common types of data structures include arrays, linked lists, stacks, queues, trees, and graphs. Each structure serves a specific purpose based on the needs of the program, such as faster access with arrays or hierarchical storage with trees.
# Example of using a list (array) in Python
data = [1, 2, 3, 4, 5]
data.append(6) # Adding an element to the list
print(data) # Output: [1, 2, 3, 4, 5, 6]
In my experience, choosing the right data structure is crucial to optimizing the performance of algorithms, especially when handling large datasets.
27. What is the difference between JDBC and Hibernate?
JDBC (Java Database Connectivity) is a low-level API for connecting Java applications to databases and executing SQL statements. It requires managing SQL queries and handling database interactions manually. Hibernate, on the other hand, is an ORM (Object-Relational Mapping) framework that simplifies database interaction by mapping Java objects to database tables, eliminating the need to write SQL for basic operations.
// Example of using Hibernate for retrieving an entity
Session session = sessionFactory.openSession();
User user = session.get(User.class, userId);
Hibernate manages connections, sessions, and SQL generation, allowing me to focus on business logic rather than SQL, which can significantly speed up development.
28. How do you share code between files in JavaScript?
In JavaScript, I use modules to share code between files. By exporting functions or objects from one file and importing them into another, I can reuse code efficiently across the application.
// module.js
export function greet() {
console.log("Hello, world!");
}
// main.js
import { greet } from './module.js';
greet(); // Output: Hello, world!
This modular approach makes it easy to maintain and scale applications, as I can separate functionality into individual files.
See also: Capgemini Salesforce Developer Interview Questions
29. Explain the difference between synchronous and asynchronous programming.
In synchronous programming, tasks execute one after another, blocking the program until each task completes. Asynchronous programming, on the other hand, allows tasks to run in the background without blocking the main program flow. This is crucial in JavaScript for handling events like API calls or file reading.
// Asynchronous example with setTimeout
console.log("Start");
setTimeout(() => {
console.log("Async Task Complete");
}, 1000);
console.log("End");
In this example, “End” logs before “Async Task Complete,” illustrating how asynchronous code does not block the main execution.
30. What is a deadlock in Java, and how do you avoid it?
A deadlock in Java occurs when two or more threads are waiting indefinitely for resources held by each other. This can halt a program, as each thread is blocked by the other. I avoid deadlocks by acquiring resources in a specific order and releasing them as soon as they are no longer needed.
public void method1() {
synchronized(resource1) {
synchronized(resource2) {
// Perform operations
}
}
}
By carefully controlling the order and scope of locks, I minimize the chance of deadlocks, which is crucial in multithreaded applications.
31. What are the main differences between a process and a thread?
A process is an independent unit of execution with its own memory space, while a thread is a subset of a process that shares the process’s memory and resources. Processes are generally heavier because each one requires separate memory, while threads within the same process are lighter since they share memory. In my experience, processes are useful for tasks that need isolation (like running multiple applications), whereas threads are helpful when performing concurrent tasks within the same application to improve performance without consuming additional memory.
// Java example of creating a thread within a process
public class ThreadExample extends Thread {
public void run() {
System.out.println("Thread is running");
}
public static void main(String[] args) {
ThreadExample thread = new ThreadExample();
thread.start(); // Executes within the same process
}
}
This code shows how a thread is created within a Java application, leveraging shared resources, which contrasts with spawning separate processes that would each consume distinct memory.
32. What is the difference between Fail-Fast and Fail-Safe iterators?
Fail-Fast iterators throw a ConcurrentModificationException
if the collection is modified while iterating. This behavior helps in early error detection. Fail-Safe iterators, on the other hand, don’t throw exceptions as they work on a copy of the collection, allowing concurrent modifications. I find Fail-Fast iterators useful when strict collection consistency is needed, while Fail-Safe iterators offer flexibility in cases where minor discrepancies in the collection can be tolerated.
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
for (String item : list) {
list.add("C"); // Causes ConcurrentModificationException
}
This code illustrates a Fail-Fast iterator: modifying list
during iteration throws an exception, as it detects concurrent modifications.
33. Why is the “this” operator inconsistent in JavaScript?
In JavaScript, the this
keyword refers to the context in which a function is called, rather than where it’s defined. This behavior leads to inconsistencies, especially in nested functions or with event listeners. In my experience, I use arrow functions to address these inconsistencies, as they inherit this
from the surrounding lexical scope, making the behavior more predictable.
const obj = {
name: "Alice",
greet: function() {
setTimeout(() => {
console.log(`Hello, ${this.name}`); // 'this' refers to obj due to arrow function
}, 1000);
}
};
obj.greet();
Using arrow functions like this ensures this
correctly points to obj
inside greet
, which is particularly helpful in asynchronous code.
See also: Salesforce Approval Process Interview Questions
34. What is the difference between Host objects and Native objects in JavaScript?
In JavaScript, Native objects are built-in to the language (like Object
, Array
, and Date
), while Host objects are provided by the environment, such as the window
and document
objects in a browser. Host objects vary by environment, whereas native objects are consistent across all JavaScript engines. In my experience, understanding this difference is essential when working across different JavaScript environments, as it helps ensure compatibility.
35. How do you handle browser compatibility issues?
To handle browser compatibility issues, I use polyfills for unsupported features, test across multiple browsers, and leverage CSS prefixes or feature detection tools like Modernizr. Additionally, I often rely on transpilers like Babel to convert modern JavaScript into code compatible with older browsers. In my experience, planning for compatibility early and thoroughly testing help avoid unexpected behavior across different browsers.
36. What is an application server, and how does it work?
An application server is a software framework that provides an environment to run applications, often handling the business logic and serving data to a client. It interacts with a web server to process requests, and it may include components like session management, database connections, and caching. By centralizing these functions, application servers streamline communication and enhance the performance of applications.
See also: Salesforce Apex Interview Questions
37. How do you manage memory leaks in JavaScript applications?
To manage memory leaks in JavaScript applications, I carefully monitor variables and DOM elements to avoid holding references unnecessarily. For example, clearing timers, removing event listeners, and nullifying variables when they’re no longer needed help prevent memory leaks. In my experience, using tools like Chrome DevTools for memory profiling has been invaluable for identifying and fixing leaks.
// Example of clearing an event listener to prevent memory leaks
const button = document.getElementById("myButton");
function handleClick() {
console.log("Button clicked");
}
button.addEventListener("click", handleClick);
// Later, remove the listener to free memory
button.removeEventListener("click", handleClick);
In this example, removing the event listener when it’s no longer necessary helps release memory, which is critical for long-running applications.
38. What is the purpose of the Service Worker in a Progressive Web App (PWA)?
A Service Worker is a script that runs in the background, enabling features like offline support, push notifications, and background syncing in Progressive Web Apps (PWAs). By caching resources, it ensures the app can function offline or with limited connectivity. In my experience, Service Workers greatly enhance the user experience in PWAs by providing reliable performance in unpredictable network conditions.
// Registering a Service Worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then((registration) => console.log('Service Worker registered'))
.catch((error) => console.log('Service Worker registration failed', error));
}
Here, registering a Service Worker allows the app to handle offline capabilities, a core feature of PWAs.
See also: Infosys React JS Interview Questions
39. How do you implement lazy loading of images in a web application?
To implement lazy loading of images, I load images only when they enter the viewport, which improves page load time by delaying resource loading until necessary. I use the loading="lazy"
attribute in HTML for simplicity, or the Intersection Observer API in JavaScript for more control.
// Using Intersection Observer API for lazy loading
const images = document.querySelectorAll("[data-src]");
const imageObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src; // Load image
img.removeAttribute("data-src");
imageObserver.unobserve(img);
}
});
});
images.forEach((img) => {
imageObserver.observe(img);
});
In this example, the Intersection Observer watches for when images enter the viewport, loading them only when visible. This is effective for enhancing performance on image-heavy sites.
40. What is the difference between synchronous and asynchronous programming in JavaScript?
In synchronous programming, tasks run sequentially, meaning each task waits for the previous one to complete. Asynchronous programming, on the other hand, allows tasks to run independently, enabling faster responses to user interactions and API calls. I find asynchronous programming essential in JavaScript for handling network requests and long-running tasks without blocking the main thread.
// Asynchronous example with a fetch API call
console.log("Start");
fetch("https://api.example.com/data")
.then(response => response.json())
.then(data => console.log("Data loaded", data));
console.log("End");
In this example, “End” logs immediately after “Start,” while the data loads asynchronously. This approach helps create smoother, more responsive applications.
Conclusion
To stand out in an intermediate or senior full-stack developer interview, it’s crucial to showcase not only your technical proficiency but also your ability to solve complex problems and communicate effectively within a team. Interviewers are looking for candidates who can seamlessly navigate both front-end and back-end development, demonstrating a deep understanding of the full technology stack. Preparing for these key topics will help you confidently tackle questions that test your real-world skills, from system design to troubleshooting, ensuring you’re ready for any challenge that comes your way.
What sets successful candidates apart is their ability to think on their feet, adapt to new tools, and integrate solutions across various platforms. This guide is designed to help you sharpen your knowledge, equipping you with both the technical expertise and the practical experience needed to excel. By mastering these critical areas, you’ll not only be prepared for the interview but also position yourself as a strong asset capable of driving innovation and efficiency within any development team.