Q6: What is the difference between synchronous and asynchronous JavaScript?
In JavaScript, operations can be either synchronous or asynchronous.
console.log('Start');
for (let i = 0; i < 1000000000; i++) {} // Long-running task
console.log('End');
console.log('Start');
setTimeout(() => {
console.log('Timeout');
}, 1000);
console.log('End');
console.log('Start');
new Promise((resolve) => {
setTimeout(() => {
resolve('Promise resolved');
}, 1000);
}).then((message) => {
console.log(message);
});
console.log('End');
Q7: Explain the concept of closures in JavaScript.
A closure in JavaScript is a function that has access to its own scope, the scope of the outer function, and the global scope. Closures are created when a function is defined within another function, allowing the inner function to access the variables of the outer function even after the outer function has finished executing.
function outerFunction(outerVariable) {
return function innerFunction(innerVariable) {
console.log('Outer Variable:', outerVariable);
console.log('Inner Variable:', innerVariable);
};
}
const newFunction = outerFunction('outside');
newFunction('inside');
In the example above,
innerFunction
is a closure that has access to
outerVariable
even after
outerFunction
has returned.
Q8: What are JavaScript Promises, and how do they work?
A Promise in JavaScript is an object that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Promises provide a way to handle asynchronous operations more efficiently and avoid callback hell.
then()
: Attaches callbacks for the fulfilled or rejected states.
catch()
: Attaches a callback for only the rejected state.
finally()
: Attaches a callback that executes regardless of the promise's outcome.
const promise = new Promise((resolve, reject) => {
const success = true;
if (success) {
resolve('Operation succeeded');
} else {
reject('Operation failed');
}
});
promise
.then((message) => {
console.log(message); // 'Operation succeeded'
})
.catch((error) => {
console.error(error);
})
.finally(() => {
console.log('Operation complete');
});
Q9: What is the purpose of the async and await keywords in JavaScript?
The
async
and
await
keywords in JavaScript provide a way to handle asynchronous operations more efficiently, making the code easier to read and write.
async
: Declares an asynchronous function. When called, an
async
function returns a Promise.
await
: Pauses the execution of an
async
function and waits for the resolution of a Promise. It can only be used inside
async
functions.
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error fetching data:', error);
}
}
fetchData();
In the example above,
fetchData
is an
async
function that uses
await
to pause execution until the Promise returned by
fetch
resolves.
Q10: What is the Virtual DOM, and how does it differ from the real DOM?
The Virtual DOM is an in-memory representation of the real DOM elements generated by a library like React. It is a lightweight copy of the real DOM and helps optimize rendering performance.
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
increment = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
{this.state.count}
);
}
}
In this example, updating the state (
this.setState
) triggers a re-render of the Virtual DOM. React's diffing algorithm then updates only the necessary parts of the real DOM.
Request question
Please fill in the form below to submit your question.
Q11: Explain the concept of CSS Flexbox and its key properties.
CSS Flexbox (Flexible Box Layout) is a layout model designed to provide a more efficient way to distribute space and align items within a container, even when their size is unknown or dynamic. It simplifies complex layouts and offers a flexible and responsive design.
display: flex;
: Defines a flex container and enables flexbox for its children.
flex-direction
: Specifies the direction of the flex items (
row
,
row-reverse
,
column
,
column-reverse
).
justify-content
: Aligns flex items along the main axis (
flex-start
,
flex-end
,
center
,
space-between
,
space-around
,
space-evenly
).
align-items
: Aligns flex items along the cross axis (
flex-start
,
flex-end
,
center
,
baseline
,
stretch
).
flex-wrap
: Controls whether flex items should wrap or not (
nowrap
,
wrap
,
wrap-reverse
).
order
: Controls the order of flex items (default is 0).
flex-grow
: Defines the ability of a flex item to grow relative to the rest.
flex-shrink
: Defines the ability of a flex item to shrink relative to the rest.
flex-basis
: Specifies the initial size of a flex item before space distribution.
align-self
: Overrides the
align-items
value for a specific flex item.
Q12: What are CSS Grid Layout and its advantages over Flexbox?
CSS Grid Layout is a two-dimensional layout system for the web. It allows you to create complex layouts on a grid structure with rows and columns. It provides more control over both horizontal and vertical alignment of items, making it more powerful for creating complex and responsive layouts.
display: grid;
: Defines a grid container and enables grid layout for its children.
grid-template-columns
: Defines the columns of the grid.
grid-template-rows
: Defines the rows of the grid.
grid-gap
: Specifies the gap between rows and columns.
grid-template-areas
: Allows you to define named grid areas for layout.
grid-column
: Specifies the start and end positions of a grid item along the column axis.
grid-row
: Specifies the start and end positions of a grid item along the row axis.
grid-area
: Allows an item to be placed in a named grid area.
Q13: What are higher-order components (HOCs) in React?
Higher-Order Components (HOCs) in React are advanced techniques for reusing component logic. An HOC is a function that takes a component and returns a new component with enhanced behavior.
import React from 'react';
// Higher-Order Component that adds logging
function withLogging(WrappedComponent) {
return class extends React.Component {
componentDidMount() {
console.log(`Component ${WrappedComponent.name} mounted`);
}
render() {
return ;
}
};
}
// Regular component
class MyComponent extends React.Component {
render() {
return Hello, {this.props.name};
}
}
// Enhanced component with logging
const MyComponentWithLogging = withLogging(MyComponent);
// Usage
function App() {
return ;
}
export default App;
In this example,
withLogging
is an HOC that enhances
MyComponent
by adding logging functionality.
Q14: What is the difference between props and state in React?
In React,
props
and
state
are both used to manage data within components, but they serve different purposes.
function ChildComponent(props) {
return {props.message};
}
function ParentComponent() {
return ;
}
setState
.
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
increment = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
Count: {this.state.count}
);
}
}
In this example,
Counter
uses state to manage the
count
value and update it when the button is clicked.
Q15: What are React hooks, and why are they used?
React Hooks are functions that let you use state and other React features in functional components. They allow you to manage component state, handle side effects, and reuse logic without writing class components.
useState
: Manages state in functional components.
useEffect
: Handles side effects like data fetching, subscriptions, and manual DOM manipulations.
useContext
: Accesses context values without using the Consumer component.
useReducer
: Manages state with a reducer function, useful for complex state logic.
import React, { useState, useEffect } from 'react';
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `Count: ${count}`;
}, [count]);
return (
Count: {count}
);
}
export default Counter;
In this example,
useState
is used to manage the
count
state, and
useEffect
is used to update the document title whenever the
count
changes.
Request question
Please fill in the form below to submit your question.
Q16: What are the key differences between client-side rendering and server-side rendering?
Client-side rendering (CSR) and server-side rendering (SSR) are two approaches for rendering web pages, each with its own advantages and use cases.
CSR Example
In CSR,
bundle.js
contains JavaScript that will render the content inside the
#app
div.
import React from 'react';
// Example with Next.js (a React framework that supports SSR):
// pages/index.js
function HomePage({ data }) {
return {data};
}
export async function getServerSideProps() {
// Fetch data from an API
const res = await fetch('https://api.example.com/data');
const data = await res.json();
return {
props: { data }, // Will be passed to the page component as props
};
}
export default HomePage;
In SSR, the HTML is generated on the server and sent to the client, ensuring the content is available immediately.
Q17: What is JSX in React, and how is it different from HTML?
JSX (JavaScript XML) is a syntax extension for JavaScript used in React to describe what the UI should look like. It allows developers to write HTML-like code within JavaScript.
className
instead of
class
).
{}
), making it easy to integrate dynamic content.
// JSX
const element = Hello, {name}!
;
// HTML
Hello, John!
Usage in React: JSX is transpiled by tools like Babel into JavaScript code that React can understand. For example, the JSX above is transpiled into:
const element = React.createElement('h1', null, `Hello, ${name}!`);
Q18: Explain the concept of "lifting state up" in React.
"Lifting state up" in React refers to moving state from child components to a common parent component. This is done to share state between multiple child components and ensure they have access to the same state data.
// ParentComponent.js
import React, { useState } from 'react';
import ChildComponentA from './ChildComponentA';
import ChildComponentB from './ChildComponentB';
function ParentComponent() {
const [sharedState, setSharedState] = useState('');
return (
);
}
export default ParentComponent;
// ChildComponentA.js
function ChildComponentA({ sharedState, setSharedState }) {
return (
setSharedState(e.target.value)}
/>
);
}
// ChildComponentB.js
function ChildComponentB({ sharedState }) {
return {sharedState}
;
}
In this example, the state is lifted to
ParentComponent
and passed down to
ChildComponentA
and
ChildComponentB
.
Q19: What are the different lifecycle methods in React class components?
React class components have several lifecycle methods that allow developers to run code at specific points during a component's life cycle. These methods are categorized into three phases: mounting, updating, and unmounting.
constructor:
Called before the component is mounted. Used to initialize state and bind event handlers.
static getDerivedStateFromProps:
Called right before rendering. Used to update state based on props.
render:
Renders the component's UI. Pure function without side effects.
componentDidMount:
Called after the component is mounted. Used for side effects like fetching data or setting up subscriptions.
static getDerivedStateFromProps:
Called right before rendering due to state or prop changes.
shouldComponentUpdate:
Determines whether the component should re-render. Used for performance optimization.
render:
Renders the component's UI.
getSnapshotBeforeUpdate:
Called right before the DOM updates. Used to capture some information from the DOM (e.g., scroll position).
componentDidUpdate:
Called after the component updates. Used for side effects that need to occur after the DOM updates.
componentWillUnmount:
Called right before the component unmounts. Used for cleanup, such as cancelling network requests or removing event listeners.
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
static getDerivedStateFromProps(nextProps, prevState) {
// Update state based on props
if (nextProps.value !== prevState.value) {
return { count: nextProps.value };
}
return null;
}
shouldComponentUpdate(nextProps, nextState) {
// Optimize performance
return nextState.count !== this.state.count;
}
getSnapshotBeforeUpdate(prevProps, prevState) {
// Capture some information from the DOM
return null;
}
componentDidMount() {
// Fetch data or set up subscriptions
}
componentDidUpdate(prevProps, prevState, snapshot) {
// Handle side effects
}
componentWillUnmount() {
// Clean up resources
}
render() {
return {this.state.count};
}
}
Q20: What are React Fragments, and why are they used?
React Fragments are a way to group multiple elements without adding extra nodes to the DOM. They allow you to return multiple elements from a component's render method without needing a wrapper element like a
div
.
: The full syntax for using a fragment.
<>...
instead of
...
.
// Using React.Fragment
function List() {
return (
Item 1
Item 2
Item 3
);
}
// Using short syntax
function List() {
return (
<>
Item 1
Item 2
Item 3
);
}
In this example,
List
returns multiple
elements without wrapping them in an additional element.
Request question
Please fill in the form below to submit your question.
Request question
Please fill in the form below to submit your question.
Request question
Please fill in the form below to submit your question.
(Basic)
The issue in the code is that the class name "active" is being added and removed correctly, but the styling isn't applied due to incorrect usage of the classList property.
Corrected code:
The provided code is correct and should work as intended. If there's no observed change, it might be due to caching issues. Ensure the browser cache is cleared or try a different browser.
(Basic)
function sumArray(arr) {
let sum = 0;
for (let i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
const numbers = [1, 2, 3, 4, 5];
console.log(sumArray(numbers)); // Output: 15
The provided code is already efficient for small arrays, but we can use the reduce method for a more concise solution.
function sumArray(arr) {
return arr.reduce((sum, current) => sum + current, 0);
}
const numbers = [1, 2, 3, 4, 5];
console.log(sumArray(numbers)); // Output: 15
(Intermediate)
console.log(0.1 + 0.2);
console.log(0.1 + 0.2 === 0.3);
The output will be:
0.30000000000000004
false
Explanation: JavaScript uses floating-point arithmetic for numbers, which can lead to precision errors. The sum of 0.1 and 0.2 is 0.30000000000000004 due to the way floating-point numbers are represented in binary. Therefore, 0.1 + 0.2 === 0.3 evaluates to false.
(Intermediate)
function capitalizeWords(str) {
// Your code here
}
console.log(capitalizeWords('hello world')); // Output: 'Hello World'
function capitalizeWords(str) {
return str.split(' ').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');
}
console.log(capitalizeWords('hello world')); // Output: 'Hello World'
(Intermediate)
function intersection(arr1, arr2) {
return arr1.filter(value => arr2.includes(value));
}
const array1 = [1, 2, 3, 4, 5];
const array2 = [4, 5, 6, 7, 8];
console.log(intersection(array1, array2)); // Output: [4, 5]
To improve performance, we can use a Set to reduce the time complexity of the lookup operation from O(n) to O(1).
function intersection(arr1, arr2) {
const set2 = new Set(arr2);
return arr1.filter(value => set2.has(value));
}
const array1 = [1, 2, 3, 4, 5];
const array2 = [4, 5, 6, 7, 8];
console.log(intersection(array1, array2)); // Output: [4, 5]
(Intermediate)
async function fetchData() {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
}
fetchData();
The provided code is correct. If there's an error, it might be due to network issues or an incorrect API endpoint. For debugging, add error handling:
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Fetch error:', error);
}
}
fetchData();
(Advanced)
function flattenArray(arr) {
// Your code here
}
console.log(flattenArray([1, [2, [3, [4]], 5]])); // Output: [1, 2, 3, 4, 5]
function flattenArray(arr) {
return arr.reduce((flat, toFlatten) => {
return flat.concat(Array.isArray(toFlatten) ? flattenArray(toFlatten) : toFlatten);
}, []);
}
console.log(flattenArray([1, [2, [3, [4]], 5]])); // Output: [1, 2, 3, 4, 5]
(Advanced)
let a = 10;
let b = a;
a = 20;
console.log(a, b);
const obj1 = { name: 'Alice' };
const obj2 = obj1;
obj1.name = 'Bob';
console.log(obj1.name, obj2.name);
The output will be:
20 10
Bob Bob
Explanation:
let b = a
creates a copy of the value. Changing
a
to 20 does not affect
b
, so
b
remains 10.
const obj2 = obj1
creates a reference to the same object in memory. Changing the
name
property of
obj1
also affects
obj2
, since both variables reference the same object.
(Advanced)
function concatenateStrings(arr) {
let result = '';
for (let i = 0; i < arr.length; i++) {
result += arr[i];
}
return result;
}
const strings = ['Hello', ' ', 'World', '!'];
console.log(concatenateStrings(strings)); // Output: 'Hello World!'
The provided code has a time complexity of O(n^2) due to string concatenation in a loop. Using
join
improves performance to O(n).
function concatenateStrings(arr) {
return arr.join('');
}
const strings = ['Hello', ' ', 'World', '!'];
console.log(concatenateStrings(strings)); // Output: 'Hello World!'
(Advanced)
function longestUniqueSubstring(s) {
// Your code here
}
console.log(longestUniqueSubstring('abcabcbb')); // Output: 'abc'
function longestUniqueSubstring(s) {
let longest = '';
let current = '';
for (let char of s) {
if (!current.includes(char)) {
current += char;
if (current.length > longest.length) {
longest = current;
}
} else {
current = current.slice(current.indexOf(char) + 1) + char;
}
}
return longest;
}
console.log(longestUniqueSubstring('abcabcbb')); // Output: 'abc'
Overview of Frontend