Accreditation Bodies
Accreditation Bodies
Accreditation Bodies
Supercharge your career with our Multi-Cloud Engineer Bootcamp
KNOW MOREThe process of creating the visual elements that users see and interact with within a web application is known as front-end development. The frontend developer is responsible for creating a web application. This guide will help you to gain confidence and knowledge about front end development, no matter if you're a beginner, intermediate, or experienced frontend professional. This course covers a variety of HTML5, CSS3, JS, and React JS questions at a basic through advanced level. So, if you are looking to advance your career in a Front-end developer, this guide is the perfect resource for you. Don't wait any longer, start preparing for your interview today! Check out this list of top, expert-curated Front end Developer interview questions and answers to help you pass interviews related to Frontend development. Take advantage of these technical interview questions and answers to ace your next job interviews in big organizations.
In JavaScript, event capturing and event bubbling is two different ways that events can propagate through the Document Object Model (DOM). Event capturing is the process by which an event travels from the top of the DOM down to the target element, while event bubbling is the process by which an event travels from the target element up to the top of the DOM.
Both event capturing and event bubbling allow you to attach multiple event listeners to a single element and control the order in which they are executed. This can be useful for creating complex event-driven applications.
Here is an example of how event capturing and event bubbling work:
<div id="outer"> <div id="inner"><button>Click me</button></div> </div>
In this example, the button is the target element. If the button is clicked, the event will first be captured by the inner element, then by the outer element.
If we attach an event listener to the outer element using the addEventListener method and set the useCapture option to true, the event will be captured by the outer element first and then trickle down to the inner element.
This is an example of event capturing.
document.getElementById('outer').addEventListener('click', function(event) { console.log('Outer element clicked'); }, true);
This is one of the most frequently asked Front-end interview questions.
JavaScript allows us to check the empty state of an object by using the Object.keys() method, which returns an array of the object's own enumerable properties. If the object has no properties, the Object.keys() method will return an empty array.
We can use the length property of the array returned by Object.keys() to check if the object is empty or not. If the length of the array is 0, the object is empty.
Here is an example of how to check if an object is empty in JavaScript:
function isObjectEmpty(obj) { return Object.keys(obj).length === 0; } var obj = {}; console.log(isObjectEmpty(obj)); // Output: true obj = { a: 10, b: 12 }; console.log(isObjectEmpty(obj)); // Output: false
console.log(2 + true); console.log(true + ‘2’);
In JavaScript, boolean values are treated as numbers when used in arithmetic operations. true is treated as the number 1, and false is treated as the number 0. Therefore, the + operator performs addition and returns the sum of 2 and 1, which is 3.
In this case, the operands are the boolean value true and the string "2". Since one of the operands is a string, the + operator concatenates them, resulting in the string "true2".
A callback function in JavaScript is a function that is passed as an argument to another function and is executed after the latter function has completed its execution. Callback functions are commonly used in JavaScript and other programming languages to perform certain actions after an event has occurred or to execute a function asynchronously.
For example, a callback function may be passed as an argument to an event listener function, which will execute the callback function when the specified event occurs. Callback functions are often used to perform tasks that may take a long time to complete, such as making an HTTP request or reading from a file without blocking the main execution thread.
Expect to come across this, one of the most popular UI developer interview questions.
CSS selectors are used to select elements on an HTML page and apply styles to them. There are various types of CSS selectors, including element selectors, class selectors, and ID selectors, which can be used to select elements based on their tag name, class name, or ID, respectively.
Some examples of CSS selectors:
Here are the differences -
Block elements:
Inline elements:
Inline-block elements:
A must-know for anyone heading into a Front-end developer interview, this is one of the most frequently asked Front-end developer questions.
The visibility property specifies whether an element is visible or not. When an element's visibility is set to hide, the element is still present in the HTML code, but is not visible to the user. This means that the element takes up the required space on the page but is not visible.
The display property specifies how an element should be displayed on the page. When an element's display is set to none, the element is not present in the layout of the page at all. This means that the element does not take up any space on the page and is not visible to the user.
Expect to come across front-end developer questions on this topic more often than others.
The practise of making website or web application accessible to the disabled users is known as web accessibility. The term encompasses people who are blind, deaf, or who have limited mobility or cognitive abilities. The four guiding principles of web accessibility must be closely followed to ensure solid web accessibility i.e.
Below are a few examples of how web accessibility can be implemented on a website:
By using float CSS property, elements are placed on either left or right sides of their container, allowing text and inline elements to wrap around them. When an element is set to float, it is removed from the normal flow of the document and positioned to the left or right of its parent element.
img { float: left; width: 50%; }
In this example, the float property is set to left and the width property is set to 50%. This will cause the image to float to the left of its parent element and take up 50% of the available width. The text on the page will then wrap around the image.
This reverseString function takes a string as an argument and uses the split(), reverse(), and join() methods to reverse it.
function reverseString(str) { return str.split('').reverse().join(''); } let reversed = reverseString("hello"); console.log(reversed); // outputs "olleh"
Array destructuring is a way to extract elements from an array and assign them to variables in a concise and convenient way. It is a feature in JS that allows you to extract multiple values from an array and assign them to individual variables with a single assignment statement.
let colors = ["red", "green", "blue"]; let [first, second, third] = colors; console.log(first, second, third); // outputs red green blue
As the number of callback functions increases, the program's code can become difficult to understand and manage, leading to what is known as "callback hell". Callback hell can occur when a program relies heavily on asynchronous function calls that require the use of callback functions to handle their results.
To avoid callback hell, it is often recommended to use more modern approaches to asynchronous programming, such as promises or async/await, which can help to make the code more readable and easier to maintain.
The Fibonacci series function uses a recursive approach to calculate the nth number in the series. The function calls itself with n - 1 and n - 2 as arguments until it reaches the base case, at which point it returns the value of n.
function fibonacci(n) { if (n <= 1) { return n; } return fibonacci(n - 1) + fibonacci(n - 2); } console.log(fibonacci(10)); // outputs 55
The clearfix is used to clear floating elements from the flow of a web page. It is often used when a container element contains floating child elements and the container element's height is not being expanded to enclose the floating elements.
One way to implement clearfix technique is to use the :after pseudo-element to create a new element that is inserted after the container element.
.container:after { content: ""; display: table; clear: both; }
In this example,
Semantics tags are the elements that have a certain meaning. Even if you are not from the technical background, you are able to understand the meaning of those tags. In short, HTML elements that clearly describe their meaning in a human-and machine-readable way are semantic. Both browsers and developers can clearly understand its meaning.
HTML5 has introduced many semantic elements. Some of them are:
Meta tags are fragments of code that tell search engines important information about your webpage, such as how they should post it in the search result. All web pages have meta tags placed in the head section, but they are only visible in HTML code. Search engine rankings and click-through rates are affected by meta tags because they determine how your website appears in search results.
Example of some meta tags:
<head> <meta name = “description” content = “Tutorials”> <meta name = “viewport” content = “width=device-width, initial-scale=1.0”> </head>
The following table compares the different types of storage that are available in browsers.
Session Storage | Local Storage | Cookies |
---|---|---|
Since data is only stored for the current session, it will be deleted when the browser is closed. | Closing the browser does not delete the stored data. | The expiration time for the data can be specified. |
Data storage capacity: 5MB. | Data storage capacity: 10MB. | Data storage capacity: Limited to 4KB. |
|
|
|
Typically used for storing login credentials and other sensitive data. | Useful for storing preferences or settings you want to persist or for offline data storage. | Used for storing data that shouldn't be retained for a long time, such as user preferences, and for storing session IDs. |
Data stored on: Browser. | Data stored on: Browser and system | Data stored on: Browser. |
Data Sent with request from client to server: No | Data Sent with request from client to server: No | Data Sent with request from client to server: Yes |
Some of the common HTML5 APIs are:
In HTML, it is necessary to include a DOCTYPE declaration. The DOCTYPE is not an element or HTML tag, but rather a directive that tells the browser how to interpret the document. It specifies the version or standard of HTML (or other markup language) that is being used.
If the DOCTYPE is not included in the HTML document, the browser may enter Quirks mode. In Quirks mode, the behaviour of the browser may vary based on the version of the browser and may not support certain HTML5 tags.
There are several ways to align an element horizontally and vertically in the center of a page or container using CSS:
.element { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
.container { display: flex; align-items: center; justify-content: center; }
.container { display: grid; place-items: center; }
.container { display: grid; place-items: center; }
.container { text-align: center; } .element { display: inline-block; line-height: 100%; }
We can use Flexbox to align all the elements within a single row. To do this, we can create a parent element (such as a <ul> element) and place several child elements (such as <li> elements) inside it. Then, we can set the display property of the parent element to "flex" to align the child elements in a single row.
Here is an example of how we can use CSS and Flexbox to align four elements in the left corner and one element in the right corner of a container/parent:
.parent { display: flex; justify-content: space-between; } .parent > *:not(:last-child) { margin-right: auto; }
The justify-content: space-between property evenly distributes the space between the elements, and the margin-right: auto property pushes the last element to the right corner of the container.
Note: This code assumes that the elements are direct children of the container element <ul> and are siblings of each other. If the elements are not direct children, you may need to adjust the CSS selector accordingly.
If we have added a margin of 10px to the bottom of the first paragraph and a margin of 10px to the top of the second paragraph, the total margin will be 10px. This is because the margins are collapsible. In this case, the margin bottom of the first paragraph, and the margin top of the second paragraph will overlap each other resulting in total 10px margin in between not 20px.
The box model is a way of representing the space that an element occupies in a web page. It consists of the element's content, padding, border, and margin. The box model is important to understand when working with CSS because it determines the size and position of elements on a web page.
A variable which is not assigned any value is ‘undefined’. It is the default value of uninitialized variables, function arguments that have not been assigned a value, and properties that do not exist. Example in the below code snippet, y and typeof y both are undefined as variable y is not assigned any value.
let y; console.log(y); / /undefined console.log(typeof y) // undefined
Null means nothing. We can assign a variable with a null value. Example:
let y = null; console.log(y); //null console.log(typeOf x) //object.
Undefined is a property of the global object, while null is a primitive value. For example, the expression typeof undefined will return "undefined", while the expression typeof null will return "object".
The onload and onloadstart events are both events that can be used in web development to trigger actions when a resource has finished loading. Despite these similarities, there are some important differences.
Onload Event
Onloadstart Event
Difference between the two events is that onload is fired for all resources, while onloadstart is only fired for the first resource in the document. This means that onload can be used to track the loading of multiple resources, while onloadstart is only fired once when the document begins to load.
In JavaScript, the forEach and map array methods are both used to iterate over the elements of an array and perform an operation on each element. Nevertheless, there are some significant differences between them.
The forEach method is used to iterate over an array and perform a function on each element. It does not return a new array and modify the original array. However, unlike forEach, map returns a new array that contains the modified elements. The map method is often used when you want to transform the elements of an array and create a new array with the modified elements.
Here is an example of how we can use the forEach and map methods:
const arrayNum = [1, 2, 3, 4, 5]; // Using forEach arrayNum.forEach(el => console.log(el * 2)); // Using map const numDouble = arrayNum.map(el => el * 2); console.log(numDouble); // [2, 4, 6, 8, 10]
Variables are declared with let and var in JavaScript. Let and var differ primarily in their scope. A let declaration is block-scoped and is not hoisted, whereas a var declaration is globally or function-scoped and is hoisted. Variables declared as var can be accessed throughout the script or function, whereas variables declared as let can only be accessed within their own block of code. For example:
if (true) { var x = 10; let y = 20; } console.log(x); // 10 console.log(y); // Uncaught ReferenceError: y is not defined
In this example, the var variable x is accessible outside of the block in which it is declared, while the let variable y is not.
Another difference between let and var is that let declarations are not hoisted to the top of the script or the top of the function, like var declarations are. This means that we cannot use a let variable before it has been declared.
console.log(x); // Uncaught ReferenceError: x is not defined let x = 10;
In this example, an error is thrown because x has not been declared before it is used. This is not the case with var declarations, which are hoisted to the top of the script or function.
console.log(x); // undefined var x = 10;
In this example, x is hoisted to the top of the script, so the console.log statement does not throw an error. However, the value of x is undefined, because the declaration has not yet been initialized.
In JavaScript, we can create an object in several ways.
const obj = new Object();
const obj = { key1: 'value1', key2: 'value2' };
const obj = Object.create({ key1: 'value1', key2: 'value2' });
class MyClass { constructor(key1, key2) { this.key1 = key1; this.key2 = key2; } } const obj = new MyClass('value1', 'value2');
The interviewer can also ask you to open any editor so he could see your programming skills.
The factorial function uses a recursive approach to calculate the factorial of a given number. It returns n * factorial(n - 1) until it reaches the base case, at which point it returns 1.
function factorial(n) { if (n === 0) { return 1; } return n * factorial(n - 1); } console.log(factorial(5)); // outputs 120
Below are some intermediate level interview questions that will help you prepare well.
When we clone an object in JavaScript, we can either create a deep copy or a shallow copy.
Shallow Copy: A shallow copy of the referenced object is created when a reference variable is copied into a new reference variable using the assignment operator. An old reference variable's value is assigned to a new reference variable by copying its address. As a result, both the old and new reference variables refer to the same object in memory. Therefore, if any one of the reference variables changes, it will affect both.
// Code Snippet for Shallow Copy var employee = { ename: "abc", salary: 50000 } console.log(employee); // {ename: “abc”, salary: “5000”} var newEmployee = employee; // Shallow copy console.log(newEmployee); // {ename: “abc”, salary: “5000”} newEmployee.ename = "xyz"; console.log(employee); // {ename: “xyz”, salary: “5000”} console.log(newEmployee); // {ename: “xyz”, salary: “5000”} // ename of employee and newEmployee both are changed.
Deep Copy: In contrast to shallow copies, deep copies make copies of all the members of an object, allocate separate memory locations for the new object, and then assign the copied members to it. Hence, both the objects are independent from one another and any changes to either one will not affect the other. JSON.parse() and JSON.stringify() allow us to deep copy objects in JavaScript.
When the object has serializable properties and is small, this method is useful. However, if the object is very large and contains certain non-serializable properties, data loss may occur. So, CloneDeep() Method from Lodash library is the better way to deep clone the object.
A common occurrence in Front-end developer questions, don't miss this one.
One of the most frequently posed junior Front-end developer interview questions, be ready for it.
Arrow functions are a shorthand syntax for defining functions in JavaScript. They are similar to regular functions but have a shorter syntax and some differences in behaviour.
One of the main benefits of using arrow functions is that they can help reduce the amount of code we need to write.
For example, we can define a function with a single statement and no function keyword or curly braces:
const add = (a, b) => a + b; This is equivalent to: const add = function(a, b) { return a + b; };
Arrow functions also have a lexical this value, which means that this value inside the function is the same as the value outside the function. This can be useful when we need to access this inside a callback function, For example;
const obj = { message: 'Hello', sayHello: () => { console.log(this.message); } }; obj.sayHello(); // logs "Hello"
This is different from regular functions, where the value of this is determined by how the function is called.
A pure function is a function that has the following properties:
Pure functions have several benefits:
It is generally a good idea to write pure functions whenever possible, as they can help to make your code more predictable, maintainable, and efficient.
A staple in Front-end interview questions and answers, be prepared to answer this one.
A closure is a function that has access to the variables in its lexical scope, even when it is executed outside of that scope. Closures are created every time a function is defined inside another function. The inner function has access to the variables and parameters of the outer function, even after the outer function has returned.
Example:
function outerFunction(x) { let y = x; function innerFunction() { console.log(y) } return innerFunction; } const myClosure = outerFunction(5); myClosure(); // logs 5
In this example, the innerFunction has access to the y variable, even though it is defined and executed outside the outerFunction. This is because innerFunction is a closure that has access to the variables in its lexical scope.
Closures are often used to create private variables and functions that can only be accessed from within a specific scope. They can also be used to keep track of the state and create callback functions that have access to that state.
Overall, closures are an important and powerful concept in JavaScript, and they are often used to create more modular and maintainable code.
In JavaScript, hoisting is the behaviour of moving declarations to the top of the current scope. This means that declarations of variables and functions are automatically moved to the top of their containing scope, regardless of where they appear in the code.
For example, consider the following code:
console.log(x); //undefined var x = 5;
Even though the declaration of the x variable appears after the first line of code, the x variable is actually defined at the top of the current scope (in this case, the global scope). This means that the first line of code will output undefined, rather than throwing a reference error.
Hoisting only affects declarations, not assignments. This means that the following code will throw a reference error, because the assignment to x is not hoisted:
console.log(x); // Uncaught ReferenceError: x is not defined x = 5;
Overall, hoisting is an important concept to understand in JavaScript, as it can affect the way your code is executed and can lead to some subtle bugs if you're not careful.
In JavaScript, the spread operator (represented by three dots: "...") allows you to expand or "spread" an iterable object (such as an array or string) into individual elements. It can be used in a variety of ways, including in function calls, array literals, and object literals.
Here are a few examples of how the spread operator can be used:
In function calls:
let numbers = [1, 2, 3, 4]; // Without spread operator Math.max(numbers); // Returns NaN (not a number) // With spread operator Math.max(...numbers); // Returns 4
In array literals:
let array1 = [1, 2, 3]; let array2 = [4, 5, 6]; // Without spread operator let combined = [array1, array2]; // [[1, 2, 3], [4, 5, 6]] // With spread operator let combined = [...array1, ...array2]; // [1, 2, 3, 4, 5, 6]
In object literals (when used in combination with the "Object.assign" function):
let obj1 = { a: 5, b: 10 }; let obj2 = { c: 3, d: 4 }; // Without spread operator let merged = Object.assign(obj1, obj2); // { a: 5, b: 10, c: 3, d: 4 } // With spread operator let merged = { ...obj1, ...obj2 }; // { a: 5, b: 10, c: 3, d: 4 }
The rest operator (also represented by three dots: "...") is like the spread operator, but it works in the opposite direction. It allows you to "gather" or condense multiple elements into a single element. It is primarily used in function parameter lists to represent an indefinite number of arguments as an array.
Below is an example of how the rest operator can be used:
function sum(...numbers) { let result = 0; for (const number of numbers) { result += number; } return result; } console.log(sum(1, 2, 3, 4, 5)); // 15
In JavaScript, this keyword refers to the object that is currently executing the code. In different contexts, this Keyword might have a different value.
Below are a few examples of how this keyword can be used in JavaScript:
In a global context (outside of any function), this refers to the global object (usually a window in a web browser).
Console.log(this); //Outputs the global object (usually ‘window’)
When calling a function, this is the object that is called the function.
const person = { name: 'John', greet: function() { console.log(`Hello, my name is ${this.name}`); } }; person.greet(); // Outputs "Hello, my name is John"
In a constructor function (a function used to create objects), this refers to the object being created.
function Person(name) { this.name = name; this.greet = function() { console.log(`Hello, my name is ${this.name}`); }; } const john = new Person('John'); john.greet(); // Outputs "Hello, my name is John"
Front-end development interview questions like this are posed to test your coding skills, be ready to tackle it.
To focus an input element on a web page when the user clicks on the corner of the page without using JavaScript, you can use the :target pseudo-class in CSS.
Here is an example:
<a href="#input1">Click here to focus input</a> <input type="text" id="input1"> #input1:target:focus { /* styles for the input element when it is targeted and focused */ }
When the user clicks on the link element, the input element will be targeted and focused, and the styles specified in the :target:focus rule will be applied to it.
To find the kth closest element to a particular value in an array, we can use the following approach:
function findKthClosest(array, value, k) { const sortedArray = array.sort((a, b) => a - b); const index = sortedArray.indexOf(value); if (index === -1) { return null; } return sortedArray[index + k] || null; } const array = [1, 3, 5, 7, 9]; const value = 5; const k = 2; const result = findKthClosest(array, value, k); console.log(result); // 7
Let us now move up the ladder from intermediate to advanced. Listed below are a few interview questions for senior front end developers.
In React, data is passed from a parent component to a child component through props, which are short for "properties."
Props are a way for a parent component to pass data to its children, and for the children to receive and use that data. Props are passed to a child component as an object, and the child component can access the data within the object using the this.props property.
Here is an example of how a parent component might pass data to a child component using props:
import React from 'react'; // Parent component class Parent extends React.Component { render() { return ( <Child name="John" age={30} /> ); } } // Child component class Child extends React.Component { render() { return ( <p>Hello, my name is {this.props.name} and I am {this.props.age} years old.</p> ); } }
It is important to note that props are read-only, meaning that a child component cannot modify its props. If a child component needs to modify data that was passed to it via props, it should communicate this back to the parent component, which can then pass the updated data back down to the child via props. This is known as "props drilling"
One way for a child component to pass data back to its parent component is by using a callback function. A callback function is a function that is passed as a prop to the child component, and it is called by the child component when it needs to pass data back to the parent.
import React from 'react'; // Parent component class Parent extends React.Component { // Define a callback function that will be passed to the child component handleDataFromChild(data) { // Do something with the data passed from the child component } render() { return ( <Child onDataFromChild={this.handleDataFromChild} /> ); } } // Child component class Child extends React.Component { // When the child component needs to pass data back to the parent, it calls the callback function handleButtonClick() { this.props.onDataFromChild({ some: 'data' }); } render() { return ( <button onClick={this.handleButtonClick}>Send data to parent</button> ); } }
In this example, the parent component defines a callback function called handleDataFromChild, which it passes to the child component as a prop. The child component can then call this callback function whenever it needs to pass data back to the parent.
Another way for a child component to communicate data back to its parent is by using the React context API, or by using a state management library like Redux, which are typically only needed in larger applications with complex data flows and may not be necessary for smaller or simpler applications.
This is one of the frequently asked Front-end interview questions.
It is generally not recommended to call setState inside the render method of a React component. This is because render is called every time the component's state or props are updated, and calling setState inside render can cause an infinite loop.
For example, consider the following component:
class MyComponent extends React.Component { state = { count: 0, }; render() { this.setState({ count: this.state.count + 1 }); // Don't do this! return <div>{this.state.count}</div>; } }
In this component, render is called every time the component's state is updated. However, inside the render method, we are calling setState, which updates the state and triggers another call to render. This creates an infinite loop, causing the component to re-render constantly without ever stopping.
To avoid this issue, it is generally recommended to avoid calling setState inside the render method. Instead, setState should be called in response to user interactions like (clicking a button) or other events that trigger a state update.
Expect to come across this, one of the most popular front-end interview questions.
In a React application, a saga is a piece of code that is responsible for managing side effects. Side effects are actions that have an impact outside of the application, such as making a network request or interacting with a database.
Sagas are needed in React applications because side effects can often be complex and hard to manage, especially when they involve multiple steps or need to be coordinated with other actions in the application. By encapsulating side effects in a separate piece of code, called a saga, it becomes easier to manage and maintain the application.
Sagas are implemented using a library called redux saga, which is a middleware that sits between the React application and the Redux store. Redux-saga uses a combination of generator functions and an event-loop to manage side effects in a declarative and efficient way.
Below is an example of a simple saga that listens for a FETCH_USER action and makes a network request to fetch the user data:
import { takeEvery, call, put } from 'redux-saga/effects'; import api from '../api'; function* fetchUser(action) { try { const user = yield call(api.fetchUser, action.payload.userId); yield put({ type: 'FETCH_USER_SUCCESS', user }); } catch (error) { yield put({ type: 'FETCH_USER_ERROR', error }); } } function* watchFetchUser() { yield takeEvery('FETCH_USER', fetchUser); } export default watchFetchUser;
A reducer in Redux is a pure function that takes in the current state of the application, an action, and returns the next state of the application. There are no side effects associated with a pure function since it always returns the same output from the same input.
There are a few reasons why reducers are designed to be pure functions:
A must-know for anyone heading into the technical interview, this is one of the most frequently asked UI developer questions.
Redux is a state management library that is often used in React applications. It provides a simple and predictable way to manage the state of the application and to update the state in response to actions.
The basic flow of Redux can be summarized as follows:
Here is a simple example of a Redux flow in a React application:
// Action const action = { type: 'ADD_TODO', payload: { text: 'Learn Redux' } }; // Reducer function reducer(state, action) { switch (action.type) { case 'ADD_TODO': return { ...state, todos: [...state.todos, { text: action.payload.text }] }; default: return state; } } // Store const store = createStore(reducer, { todos: [] }); // Component class TodoList extends React.Component { render() { const { todos } = this.props; return ( <ul> {todos.map(todo => ( <li key={todo.text}>{todo.text}</li> ))} </ul> ); } } const mapStateToProps = state => ({ todos: state.todos }); const ConnectedTodoList = connect(mapStateToProps)(TodoList); // Dispatch action store.dispatch(action);
In this example, the ADD_TODO action is dispatched when the user clicks a button. The reducer processes the action and updates the todos array in the state. The store updates its internal state and the TodoList component re-renders to display the updated list of todos.
Redux flow is one of the most mentioned topics among Front-end developer questions, so make sure you master this topic as well.
In React, the lifecycle of a component refers to the different stages of its existence, from the moment it is created to the moment it is destroyed. In the past, React provided a set of lifecycle methods that could be used to manage the lifecycle of a component, such as componentDidMount, componentDidUpdate, and componentWillUnmount.
Starting from React 16.8, it is also possible to manage the lifecycle of a component using hooks. Hooks are functions that allow you to use state and other React features in functional components.
Below is an example of how to use the useEffect hook to manage the lifecycle of a component:
import { useEffect } from 'react'; function MyComponent() { useEffect(() => { // componentDidMount and componentDidUpdate return () => { // componentWillUnmount }; }); return <div>My component</div>; }
The useEffect hook takes a callback function as an argument, which will be called after the component is rendered. The callback function can perform side effects, such as making a network request or setting up an event listener.
The useEffect hook can also accept a second argument, which is an array of dependencies. If the dependencies change, the callback function will be called again. This allows you to specify when the effect should be run. If the array is empty, the effect will only be run once, when the component is mounted.
Here is an example of how to use the useEffect hook with dependencies:
import { useEffect, useState } from 'react'; function MyComponent() { const [count, setCount] = useState(0); useEffect(() => { console.log(`Count is ${count}`); // componentDidUpdate }, [count]); // Only re-run the effect if count changes return ( <div> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }
In React, the setState method is used to update the state of a component. It takes two arguments: the first argument is an object that specifies the state changes to be made, and the second argument is a callback function that will be called after the state has been updated.
Here is an example of how to use setState with a callback function:
class MyComponent extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } incrementCount = () => { this.setState({ count: this.state.count + 1 }, () => { console.log(`Count is now ${this.state.count}`); }); }; render() { return ( <div> <button onClick={this.incrementCount}>Increment</button> </div> ); } }
In this example, the incrementCount method updates the count state variable and logs the new value to the console using a callback function. The callback function is called after the state has been updated and the component has re-rendered.
The second argument to setState is optional, and you can omit it if you do not need to perform any actions after the state has been updated.
In a React application, a controlled component is a component that is controlled by the React state. This means that the component's value and behavior are determined by the state, and the component does not maintain its own internal state.
An uncontrolled component, on the other hand, is a component that maintains its own internal state. The value of the component is not controlled by the React state, and the component can update its own value independently of the React state.
Below is an example of a controlled text input component:
class ControlledInput extends React.Component { constructor(props) { super(props); this.state = { value: '' }; } handleChange = event => { this.setState({ value: event.target.value }); }; render() { return ( <input type="text" value={this.state.value} onChange={this.handleChange} /> ); } }
In this example, the value of the input is controlled by the value state variable, and the onChange event handler is used to update the state when the input value changes.
Below is an example of an uncontrolled text input component:
class UncontrolledInput extends React.Component { inputRef = React.createRef(); handleSubmit = event => { event.preventDefault(); console.log(this.inputRef.current.value); }; render() { return ( <form onSubmit={this.handleSubmit}> <input type="text" ref={this.inputRef} /> <button type="submit">Submit</button> </form> ); } }
In this example, the input does not have a value prop and is not controlled by the React state. Instead, the input's value is accessed directly using the ref system. When the form is submitted, the value of the input is logged to the console using the ref object.
Controlled components are generally easier to manage and test because the state of the component is fully determined by the React state. Uncontrolled components can be useful when you need to work with a DOM API or when you need to optimize performance by avoiding unnecessary re-renders.
A frequent occurrence in the list of Front-end developer technical interview questions, don't miss this one.
Generator functions are used in sagas because they provide a convenient way to pause and resume the execution of a function. This is useful when working with side effects, because it allows you to perform async operations in a declarative and efficient way.
In a saga, generator functions are used to manage the flow of the saga and to coordinate the execution of async tasks. The redux-saga library provides a set of helper functions, called effects, that can be used to pause the generator function and wait for a specific event to occur.
In HTML, a webpage can be displayed in either standards mode or quirks mode. These modes determine how a webpage is rendered by a web browser, and they can affect the way the webpage looks and behaves.
Standards mode is the preferred mode for rendering webpages, as it follows the standards set by the World Wide Web Consortium (W3C) for HTML, CSS, and other web technologies. When a webpage is displayed in standards mode, the web browser follows the standards specified in the HTML and CSS code, which ensures that the webpage is displayed consistently across different browsers.
Quirks mode, on the other hand, is a way for web browsers to handle older or improperly coded webpages. When a webpage is displayed in quirks mode, the web browser uses a different set of rules to try to display the webpage correctly. These rules are based on the way web browsers used to handle webpages in the past, and they can cause the webpage to be displayed differently in different browsers.
To determine which mode to use, web browsers look at the HTML code of the webpage and check for certain tags or attributes that indicate which mode to use.
For example, if the webpage includes a <!DOCTYPE> declaration at the top of the HTML code, the browser will use standards mode. If the <!DOCTYPE> declaration is missing or incorrect, the browser will use quirks mode.
Webpack is a module bundler for modern JavaScript applications. It is a powerful tool used by developers to write and organize their code in a modular manner, and then bundle it together into a single file (or a few files) that a web browser can load.
One of the main benefits of using webpack is that it allows developers to use the latest JavaScript features and syntax, even if the user's web browser does not support those features. Webpack also offers a range of other features and capabilities, such as:
There are several ways to reduce the page load time of a website or web application. Here are a few suggestions:
By implementing some or all of these strategies, one can significantly improve the page load time of your website or web application.
This is one of the frequently asked senior Front-end developer interview questions.
Dependency injection (DI) is a design pattern that allows an object to receive its dependencies from an external source rather than creating them itself. This can make it easier to design, test, and maintain complex systems, as it allows different components of the system to be isolated from one another and more easily modified or replaced.
In a DI system, objects are typically defined with interfaces that specify their dependencies. An external source, such as a container or factory, is responsible for creating and injecting the required dependencies into the object when it is needed. This means that the object does not need to know how to create its dependencies, or even what they are.
For example, consider a simple object that represents a car. The car object might have a dependency on an engine object, which it needs in order to operate. Without DI, the car object might create its own engine object using the new operator, like this:
class Car { constructor() { this.engine = new Engine(); } }
With DI, the car object would instead define an interface for its engine dependency, and the DI container would be responsible for creating and injecting the engine object when the car object is created:
class Car { constructor(engine) { this.engine = engine; } }
Using DI has several benefits:
Overall, dependency injection is a useful design pattern that can help to improve the modularity, testability, and maintainability of complex systems.
Lazy loading is a technique that allows content to be loaded on demand, rather than all at once. This can help to improve the performance and load time of a webpage or web application, especially if it has a lot of content.
Lazy loading can be implemented in various ways, such as:
Server-side rendering (SSR) is a technique that allows a web server to generate and serve HTML for a webpage on demand rather than relying on the client's web browser to generate the HTML. This can be useful in various situations, including:
It's no surprise that this one pops up often in UI developer interviews.
Debouncing and throttling are techniques that can be used to reduce the frequency of function calls in JavaScript. They are often used to improve the performance and efficiency of code that is triggered by events, such as user input or window resizing.
Debouncing is a technique that delays the execution of a function until a certain amount of time has passed without the function being called. This can be useful if you want to ensure that a function is not called too frequently, such as when handling user input events.
For example, consider a function that is called every time the user types a character into an input field:
document.querySelector('input').addEventListener('keyup', function() { search(); }); function search() { // Perform a search }
If the user types quickly, this function could be called many times in a short period, which could cause performance issues. To address this, we can use debouncing to delay the execution of the function until the user has finished typing:
let timeout; document.querySelector('input').addEventListener('keyup', function() { clearTimeout(timeout); timeout = setTimeout(search, 500); }); function search() { // Perform a search }
In this example, the search function is called 500 milliseconds (0.5 seconds) after the user stops typing. This helps to ensure that the function is not called too frequently, while still allowing the user to receive timely feedback.
Throttling is a technique that limits the number of times a function can be called within a certain time period. This can be useful if we want to ensure that a function is not called too frequently, but we still want it to be called at a regular interval.
For example, consider a function that is called every time the user scrolls the page:
window.addEventListener('scroll', function() { updatePosition(); }); function updatePosition() { // Update the element position }
If the user scrolls quickly, this function could be called many times in a short time, which could cause performance issues. To address this, we can use throttling to limit the number of times the function is called:
let canCall = true; window.addEventListener('scroll', function() { if (canCall) { updatePosition(); canCall = false; setTimeout(function() { canCall = true; }, 100); } }); function updatePosition() { // Update the position of an element }
In this example, the updatePosition function is called once every 100 milliseconds (0.1 seconds) while the user is scrolling. This helps to ensure that the function is not called too frequently, while still allowing it to be called at a regular interval.
In JavaScript, currying is a technique that allows a function to be partially applied, or "pre-filled," with some of its arguments. There are several situations where this can be useful, such as:
To understand how currying works, consider the following example:
function add(a, b) { return a + b; }
The function returns the sum of two arguments (a and b). To curry this function, we can create a new function that takes one of the arguments and returns a new function that takes the other argument:
function add(a) { return function(b) { return a + b; } } const add5 = add(5); console.log(add5(10)); // 15 console.log(add5(20)); // 25
In this example, the add5 function is a partially applied version of the add function, with an argument pre-filled with the value 5. This allows us to create a new function that can be easily reused to add 5 to any number.
Currying can be implemented in a variety of ways in JavaScript, and it can be used to create a wide range of reusable and flexible functions. It is a useful technique for improving the modularity, readability, and clarity of code.
setTimeout is a JavaScript function that allows us to schedule a function to be executed after a specified amount of time has passed. It works by adding a timer to the JavaScript event loop, which is a queue of tasks that are executed by the browser or runtime environment.
To illustrate how setTimeout works, here is an example:
console.log('Start'); setTimeout(function() { console.log('Timeout'); }, 1000); console.log('End');
In this example, the setTimeout function is called with a delay time of 1000 milliseconds (1 second). When this code is executed, the following will happen:
CSS pre-processors are tools that allow us to write CSS more powerfully and expressively, and then compile it into standard CSS that can be used on a web page.
There are several reasons why CSS pre-processors like SASS are preferred over plain CSS:
Overall, CSS preprocessors like SASS are preferred over plain CSS because they offer a range of benefits, including improved code organization and reuse, enhanced syntax and features, improved performance, and better compatibility with modern tools.
Prior to executing the code, we can explain the logic used in the code to the interviewer, namely using a filter method that runs on each element of the array and leaves only entries that pass the given callback function. A callback function checks whether a value has the first occurrence. If not, it must be the same value and will not be copied. This is how unique elements can be extracted from the array.
let myArray = ['ac', 12, 'ac', 12, '1']; let uniqueEl = myArray.filter((value, index, el) => el.indexOf(value) === index); console.log(uniqueEl); // unique elements are ['ac', 12, '1']
Is there any other way to implement the same?
Yes, with the help of inbuilt function Set.
let myArray = ['ac', 12, 'ac', 12, '1']; let uniqueEl = […new Set(myArray)]; console.log(uniqueEl); // unique is ['ac', 12, '1']
Afterwards, the interviewer asked me some
function abc(){ x = 10; let y = 5; } abc(); console.log(x, y);
It will return referenceError: y is not defined, as y is block scoped, and we're trying to access it outside that scope.
A staple in Front-end developer interview questions, be prepared to answer this one.
The output of first statement is "202". In JavaScript, the + operator is used for both addition and concatenation, depending on the operands. When one of the operands is a string, the + operator performs concatenation, meaning it combines the two operands as strings and returns the resulting string.
In this case, the operands are the number 20 and the string "2". Since one of the operands is a string, the + operator concatenates them, resulting in the string "202".
The output of second statement would be 18. The - operator is used for subtraction. When both operands are numbers, the - operator performs subtraction and returns the difference.
In this case, the operands are the number 20 and the string "2". Since the string "2" can be converted to the number 2, the - operator performs subtraction and returns the difference, which is 18.
A polyfill is a piece of code that provides a missing functionality in older browsers that do not support that functionality natively. One way to implement a polyfill for the map() method in JavaScript is to use a simple loop to iterate over the elements of the array and call the provided function on each element:
if (!Array.prototype.map) { Array.prototype.map = function(callback, thisArg) { var newArray = []; for (var i = 0; i < this.length; i++) { newArray.push(callback.call(thisArg, this[i], i, this)); } return newArray; } }
This polyfill checks if the map() method is not already present on the Array.prototype, and if it is not, it defines the map() method as a function that takes a callback function and an optional thisArg as arguments. The callback function is called on each element of the array, and the resulting values are pushed to a new array, which is then returned.
for (var i = 0; i < 5; i++) { setTimeout(function() { console.log(i); }, i * 1000 ); }
In this code, there is a for loop that iterates 5 times, from 0 to 4. For each iteration, the setTimeout() function is called with a callback function that logs the value of i. The value of i that is logged is not the value at the time the setTimeout() function is called, but rather the value of i after the for loop has completed.
This is because the setTimeout() function is a non-blocking function, and the callback function is not executed until the specified delay has passed. Therefore, the value of i is not captured at the time the setTimeout() function is called, but rather at the time the callback function is executed. By the time the callback function is executed, the for loop has already completed, and the value of i is 5.
So, Output is
5 5 5 5 5
To log the values of i at the time the setTimeout() function is called, you could use an immediately-invoked function expression (IIFE) to capture the value of i at each iteration of the for loop:
for (var i = 0; i < 5; i++) { (function(x) { setTimeout(function() { console.log(x); }, x * 1000 ); })(i); }
This will log the values of i at the time the setTimeout() function is called, resulting in the output:
0 1 2 3 4
HTML5 Provides a <iframe> tag to display nested webpages. Example:
<iframe src =”url of page you want to embed”>
In HTML5, headers and footers have specific tags. Instead of using a div with an id, let's use a header footer tag.
<header> <h1>Monday Times</h1> </ header > <body>.......</body> <footer> <p>Hello World!</p> </ footer >
Modals are pop-up windows or dialog boxes that appear on top of the page. Our first step will be to create an HTML DOM structure and then apply CSS3 styles to it.
The HTML structure is shown below:
<div id="modal" class="modal"> <div class="modal-content"> <span class="close">×</span> <p>Modal Text..</p> </div> </div>
Adding styling to a modal using CSS3.
.modal { position: fixed; z-index: 1; padding-top: 100px; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgb(0,0,0); background-color: rgba(0,0,0,0.4); } .modal-content { background-color: #fff; margin: auto; padding: 15px; border: 1px solid #ccc; width: 85%; } .close { color: #aaa; float: right; font-size: 25px; font-weight: 700; cursor: pointer; }
Once the coding interview is finished, the interviewer starts with the react front end interview questions. Some of the important questions listed below will help you crack your interview.
In JavaScript, event capturing and event bubbling is two different ways that events can propagate through the Document Object Model (DOM). Event capturing is the process by which an event travels from the top of the DOM down to the target element, while event bubbling is the process by which an event travels from the target element up to the top of the DOM.
Both event capturing and event bubbling allow you to attach multiple event listeners to a single element and control the order in which they are executed. This can be useful for creating complex event-driven applications.
Here is an example of how event capturing and event bubbling work:
<div id="outer"> <div id="inner"><button>Click me</button></div> </div>
In this example, the button is the target element. If the button is clicked, the event will first be captured by the inner element, then by the outer element.
If we attach an event listener to the outer element using the addEventListener method and set the useCapture option to true, the event will be captured by the outer element first and then trickle down to the inner element.
This is an example of event capturing.
document.getElementById('outer').addEventListener('click', function(event) { console.log('Outer element clicked'); }, true);
This is one of the most frequently asked Front-end interview questions.
JavaScript allows us to check the empty state of an object by using the Object.keys() method, which returns an array of the object's own enumerable properties. If the object has no properties, the Object.keys() method will return an empty array.
We can use the length property of the array returned by Object.keys() to check if the object is empty or not. If the length of the array is 0, the object is empty.
Here is an example of how to check if an object is empty in JavaScript:
function isObjectEmpty(obj) { return Object.keys(obj).length === 0; } var obj = {}; console.log(isObjectEmpty(obj)); // Output: true obj = { a: 10, b: 12 }; console.log(isObjectEmpty(obj)); // Output: false
console.log(2 + true); console.log(true + ‘2’);
In JavaScript, boolean values are treated as numbers when used in arithmetic operations. true is treated as the number 1, and false is treated as the number 0. Therefore, the + operator performs addition and returns the sum of 2 and 1, which is 3.
In this case, the operands are the boolean value true and the string "2". Since one of the operands is a string, the + operator concatenates them, resulting in the string "true2".
A callback function in JavaScript is a function that is passed as an argument to another function and is executed after the latter function has completed its execution. Callback functions are commonly used in JavaScript and other programming languages to perform certain actions after an event has occurred or to execute a function asynchronously.
For example, a callback function may be passed as an argument to an event listener function, which will execute the callback function when the specified event occurs. Callback functions are often used to perform tasks that may take a long time to complete, such as making an HTTP request or reading from a file without blocking the main execution thread.
Expect to come across this, one of the most popular UI developer interview questions.
CSS selectors are used to select elements on an HTML page and apply styles to them. There are various types of CSS selectors, including element selectors, class selectors, and ID selectors, which can be used to select elements based on their tag name, class name, or ID, respectively.
Some examples of CSS selectors:
Here are the differences -
Block elements:
Inline elements:
Inline-block elements:
A must-know for anyone heading into a Front-end developer interview, this is one of the most frequently asked Front-end developer questions.
The visibility property specifies whether an element is visible or not. When an element's visibility is set to hide, the element is still present in the HTML code, but is not visible to the user. This means that the element takes up the required space on the page but is not visible.
The display property specifies how an element should be displayed on the page. When an element's display is set to none, the element is not present in the layout of the page at all. This means that the element does not take up any space on the page and is not visible to the user.
Expect to come across front-end developer questions on this topic more often than others.
The practise of making website or web application accessible to the disabled users is known as web accessibility. The term encompasses people who are blind, deaf, or who have limited mobility or cognitive abilities. The four guiding principles of web accessibility must be closely followed to ensure solid web accessibility i.e.
Below are a few examples of how web accessibility can be implemented on a website:
By using float CSS property, elements are placed on either left or right sides of their container, allowing text and inline elements to wrap around them. When an element is set to float, it is removed from the normal flow of the document and positioned to the left or right of its parent element.
img { float: left; width: 50%; }
In this example, the float property is set to left and the width property is set to 50%. This will cause the image to float to the left of its parent element and take up 50% of the available width. The text on the page will then wrap around the image.
This reverseString function takes a string as an argument and uses the split(), reverse(), and join() methods to reverse it.
function reverseString(str) { return str.split('').reverse().join(''); } let reversed = reverseString("hello"); console.log(reversed); // outputs "olleh"
Array destructuring is a way to extract elements from an array and assign them to variables in a concise and convenient way. It is a feature in JS that allows you to extract multiple values from an array and assign them to individual variables with a single assignment statement.
let colors = ["red", "green", "blue"]; let [first, second, third] = colors; console.log(first, second, third); // outputs red green blue
As the number of callback functions increases, the program's code can become difficult to understand and manage, leading to what is known as "callback hell". Callback hell can occur when a program relies heavily on asynchronous function calls that require the use of callback functions to handle their results.
To avoid callback hell, it is often recommended to use more modern approaches to asynchronous programming, such as promises or async/await, which can help to make the code more readable and easier to maintain.
The Fibonacci series function uses a recursive approach to calculate the nth number in the series. The function calls itself with n - 1 and n - 2 as arguments until it reaches the base case, at which point it returns the value of n.
function fibonacci(n) { if (n <= 1) { return n; } return fibonacci(n - 1) + fibonacci(n - 2); } console.log(fibonacci(10)); // outputs 55
The clearfix is used to clear floating elements from the flow of a web page. It is often used when a container element contains floating child elements and the container element's height is not being expanded to enclose the floating elements.
One way to implement clearfix technique is to use the :after pseudo-element to create a new element that is inserted after the container element.
.container:after { content: ""; display: table; clear: both; }
In this example,
Semantics tags are the elements that have a certain meaning. Even if you are not from the technical background, you are able to understand the meaning of those tags. In short, HTML elements that clearly describe their meaning in a human-and machine-readable way are semantic. Both browsers and developers can clearly understand its meaning.
HTML5 has introduced many semantic elements. Some of them are:
Meta tags are fragments of code that tell search engines important information about your webpage, such as how they should post it in the search result. All web pages have meta tags placed in the head section, but they are only visible in HTML code. Search engine rankings and click-through rates are affected by meta tags because they determine how your website appears in search results.
Example of some meta tags:
<head> <meta name = “description” content = “Tutorials”> <meta name = “viewport” content = “width=device-width, initial-scale=1.0”> </head>
The following table compares the different types of storage that are available in browsers.
Session Storage | Local Storage | Cookies |
---|---|---|
Since data is only stored for the current session, it will be deleted when the browser is closed. | Closing the browser does not delete the stored data. | The expiration time for the data can be specified. |
Data storage capacity: 5MB. | Data storage capacity: 10MB. | Data storage capacity: Limited to 4KB. |
|
|
|
Typically used for storing login credentials and other sensitive data. | Useful for storing preferences or settings you want to persist or for offline data storage. | Used for storing data that shouldn't be retained for a long time, such as user preferences, and for storing session IDs. |
Data stored on: Browser. | Data stored on: Browser and system | Data stored on: Browser. |
Data Sent with request from client to server: No | Data Sent with request from client to server: No | Data Sent with request from client to server: Yes |
Some of the common HTML5 APIs are:
In HTML, it is necessary to include a DOCTYPE declaration. The DOCTYPE is not an element or HTML tag, but rather a directive that tells the browser how to interpret the document. It specifies the version or standard of HTML (or other markup language) that is being used.
If the DOCTYPE is not included in the HTML document, the browser may enter Quirks mode. In Quirks mode, the behaviour of the browser may vary based on the version of the browser and may not support certain HTML5 tags.
There are several ways to align an element horizontally and vertically in the center of a page or container using CSS:
.element { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
.container { display: flex; align-items: center; justify-content: center; }
.container { display: grid; place-items: center; }
.container { display: grid; place-items: center; }
.container { text-align: center; } .element { display: inline-block; line-height: 100%; }
We can use Flexbox to align all the elements within a single row. To do this, we can create a parent element (such as a <ul> element) and place several child elements (such as <li> elements) inside it. Then, we can set the display property of the parent element to "flex" to align the child elements in a single row.
Here is an example of how we can use CSS and Flexbox to align four elements in the left corner and one element in the right corner of a container/parent:
.parent { display: flex; justify-content: space-between; } .parent > *:not(:last-child) { margin-right: auto; }
The justify-content: space-between property evenly distributes the space between the elements, and the margin-right: auto property pushes the last element to the right corner of the container.
Note: This code assumes that the elements are direct children of the container element <ul> and are siblings of each other. If the elements are not direct children, you may need to adjust the CSS selector accordingly.
If we have added a margin of 10px to the bottom of the first paragraph and a margin of 10px to the top of the second paragraph, the total margin will be 10px. This is because the margins are collapsible. In this case, the margin bottom of the first paragraph, and the margin top of the second paragraph will overlap each other resulting in total 10px margin in between not 20px.
The box model is a way of representing the space that an element occupies in a web page. It consists of the element's content, padding, border, and margin. The box model is important to understand when working with CSS because it determines the size and position of elements on a web page.
A variable which is not assigned any value is ‘undefined’. It is the default value of uninitialized variables, function arguments that have not been assigned a value, and properties that do not exist. Example in the below code snippet, y and typeof y both are undefined as variable y is not assigned any value.
let y; console.log(y); / /undefined console.log(typeof y) // undefined
Null means nothing. We can assign a variable with a null value. Example:
let y = null; console.log(y); //null console.log(typeOf x) //object.
Undefined is a property of the global object, while null is a primitive value. For example, the expression typeof undefined will return "undefined", while the expression typeof null will return "object".
The onload and onloadstart events are both events that can be used in web development to trigger actions when a resource has finished loading. Despite these similarities, there are some important differences.
Onload Event
Onloadstart Event
Difference between the two events is that onload is fired for all resources, while onloadstart is only fired for the first resource in the document. This means that onload can be used to track the loading of multiple resources, while onloadstart is only fired once when the document begins to load.
In JavaScript, the forEach and map array methods are both used to iterate over the elements of an array and perform an operation on each element. Nevertheless, there are some significant differences between them.
The forEach method is used to iterate over an array and perform a function on each element. It does not return a new array and modify the original array. However, unlike forEach, map returns a new array that contains the modified elements. The map method is often used when you want to transform the elements of an array and create a new array with the modified elements.
Here is an example of how we can use the forEach and map methods:
const arrayNum = [1, 2, 3, 4, 5]; // Using forEach arrayNum.forEach(el => console.log(el * 2)); // Using map const numDouble = arrayNum.map(el => el * 2); console.log(numDouble); // [2, 4, 6, 8, 10]
Variables are declared with let and var in JavaScript. Let and var differ primarily in their scope. A let declaration is block-scoped and is not hoisted, whereas a var declaration is globally or function-scoped and is hoisted. Variables declared as var can be accessed throughout the script or function, whereas variables declared as let can only be accessed within their own block of code. For example:
if (true) { var x = 10; let y = 20; } console.log(x); // 10 console.log(y); // Uncaught ReferenceError: y is not defined
In this example, the var variable x is accessible outside of the block in which it is declared, while the let variable y is not.
Another difference between let and var is that let declarations are not hoisted to the top of the script or the top of the function, like var declarations are. This means that we cannot use a let variable before it has been declared.
console.log(x); // Uncaught ReferenceError: x is not defined let x = 10;
In this example, an error is thrown because x has not been declared before it is used. This is not the case with var declarations, which are hoisted to the top of the script or function.
console.log(x); // undefined var x = 10;
In this example, x is hoisted to the top of the script, so the console.log statement does not throw an error. However, the value of x is undefined, because the declaration has not yet been initialized.
In JavaScript, we can create an object in several ways.
const obj = new Object();
const obj = { key1: 'value1', key2: 'value2' };
const obj = Object.create({ key1: 'value1', key2: 'value2' });
class MyClass { constructor(key1, key2) { this.key1 = key1; this.key2 = key2; } } const obj = new MyClass('value1', 'value2');
The interviewer can also ask you to open any editor so he could see your programming skills.
The factorial function uses a recursive approach to calculate the factorial of a given number. It returns n * factorial(n - 1) until it reaches the base case, at which point it returns 1.
function factorial(n) { if (n === 0) { return 1; } return n * factorial(n - 1); } console.log(factorial(5)); // outputs 120
Below are some intermediate level interview questions that will help you prepare well.
When we clone an object in JavaScript, we can either create a deep copy or a shallow copy.
Shallow Copy: A shallow copy of the referenced object is created when a reference variable is copied into a new reference variable using the assignment operator. An old reference variable's value is assigned to a new reference variable by copying its address. As a result, both the old and new reference variables refer to the same object in memory. Therefore, if any one of the reference variables changes, it will affect both.
// Code Snippet for Shallow Copy var employee = { ename: "abc", salary: 50000 } console.log(employee); // {ename: “abc”, salary: “5000”} var newEmployee = employee; // Shallow copy console.log(newEmployee); // {ename: “abc”, salary: “5000”} newEmployee.ename = "xyz"; console.log(employee); // {ename: “xyz”, salary: “5000”} console.log(newEmployee); // {ename: “xyz”, salary: “5000”} // ename of employee and newEmployee both are changed.
Deep Copy: In contrast to shallow copies, deep copies make copies of all the members of an object, allocate separate memory locations for the new object, and then assign the copied members to it. Hence, both the objects are independent from one another and any changes to either one will not affect the other. JSON.parse() and JSON.stringify() allow us to deep copy objects in JavaScript.
When the object has serializable properties and is small, this method is useful. However, if the object is very large and contains certain non-serializable properties, data loss may occur. So, CloneDeep() Method from Lodash library is the better way to deep clone the object.
A common occurrence in Front-end developer questions, don't miss this one.
One of the most frequently posed junior Front-end developer interview questions, be ready for it.
Arrow functions are a shorthand syntax for defining functions in JavaScript. They are similar to regular functions but have a shorter syntax and some differences in behaviour.
One of the main benefits of using arrow functions is that they can help reduce the amount of code we need to write.
For example, we can define a function with a single statement and no function keyword or curly braces:
const add = (a, b) => a + b; This is equivalent to: const add = function(a, b) { return a + b; };
Arrow functions also have a lexical this value, which means that this value inside the function is the same as the value outside the function. This can be useful when we need to access this inside a callback function, For example;
const obj = { message: 'Hello', sayHello: () => { console.log(this.message); } }; obj.sayHello(); // logs "Hello"
This is different from regular functions, where the value of this is determined by how the function is called.
A pure function is a function that has the following properties:
Pure functions have several benefits:
It is generally a good idea to write pure functions whenever possible, as they can help to make your code more predictable, maintainable, and efficient.
A staple in Front-end interview questions and answers, be prepared to answer this one.
A closure is a function that has access to the variables in its lexical scope, even when it is executed outside of that scope. Closures are created every time a function is defined inside another function. The inner function has access to the variables and parameters of the outer function, even after the outer function has returned.
Example:
function outerFunction(x) { let y = x; function innerFunction() { console.log(y) } return innerFunction; } const myClosure = outerFunction(5); myClosure(); // logs 5
In this example, the innerFunction has access to the y variable, even though it is defined and executed outside the outerFunction. This is because innerFunction is a closure that has access to the variables in its lexical scope.
Closures are often used to create private variables and functions that can only be accessed from within a specific scope. They can also be used to keep track of the state and create callback functions that have access to that state.
Overall, closures are an important and powerful concept in JavaScript, and they are often used to create more modular and maintainable code.
In JavaScript, hoisting is the behaviour of moving declarations to the top of the current scope. This means that declarations of variables and functions are automatically moved to the top of their containing scope, regardless of where they appear in the code.
For example, consider the following code:
console.log(x); //undefined var x = 5;
Even though the declaration of the x variable appears after the first line of code, the x variable is actually defined at the top of the current scope (in this case, the global scope). This means that the first line of code will output undefined, rather than throwing a reference error.
Hoisting only affects declarations, not assignments. This means that the following code will throw a reference error, because the assignment to x is not hoisted:
console.log(x); // Uncaught ReferenceError: x is not defined x = 5;
Overall, hoisting is an important concept to understand in JavaScript, as it can affect the way your code is executed and can lead to some subtle bugs if you're not careful.
In JavaScript, the spread operator (represented by three dots: "...") allows you to expand or "spread" an iterable object (such as an array or string) into individual elements. It can be used in a variety of ways, including in function calls, array literals, and object literals.
Here are a few examples of how the spread operator can be used:
In function calls:
let numbers = [1, 2, 3, 4]; // Without spread operator Math.max(numbers); // Returns NaN (not a number) // With spread operator Math.max(...numbers); // Returns 4
In array literals:
let array1 = [1, 2, 3]; let array2 = [4, 5, 6]; // Without spread operator let combined = [array1, array2]; // [[1, 2, 3], [4, 5, 6]] // With spread operator let combined = [...array1, ...array2]; // [1, 2, 3, 4, 5, 6]
In object literals (when used in combination with the "Object.assign" function):
let obj1 = { a: 5, b: 10 }; let obj2 = { c: 3, d: 4 }; // Without spread operator let merged = Object.assign(obj1, obj2); // { a: 5, b: 10, c: 3, d: 4 } // With spread operator let merged = { ...obj1, ...obj2 }; // { a: 5, b: 10, c: 3, d: 4 }
The rest operator (also represented by three dots: "...") is like the spread operator, but it works in the opposite direction. It allows you to "gather" or condense multiple elements into a single element. It is primarily used in function parameter lists to represent an indefinite number of arguments as an array.
Below is an example of how the rest operator can be used:
function sum(...numbers) { let result = 0; for (const number of numbers) { result += number; } return result; } console.log(sum(1, 2, 3, 4, 5)); // 15
In JavaScript, this keyword refers to the object that is currently executing the code. In different contexts, this Keyword might have a different value.
Below are a few examples of how this keyword can be used in JavaScript:
In a global context (outside of any function), this refers to the global object (usually a window in a web browser).
Console.log(this); //Outputs the global object (usually ‘window’)
When calling a function, this is the object that is called the function.
const person = { name: 'John', greet: function() { console.log(`Hello, my name is ${this.name}`); } }; person.greet(); // Outputs "Hello, my name is John"
In a constructor function (a function used to create objects), this refers to the object being created.
function Person(name) { this.name = name; this.greet = function() { console.log(`Hello, my name is ${this.name}`); }; } const john = new Person('John'); john.greet(); // Outputs "Hello, my name is John"
Front-end development interview questions like this are posed to test your coding skills, be ready to tackle it.
To focus an input element on a web page when the user clicks on the corner of the page without using JavaScript, you can use the :target pseudo-class in CSS.
Here is an example:
<a href="#input1">Click here to focus input</a> <input type="text" id="input1"> #input1:target:focus { /* styles for the input element when it is targeted and focused */ }
When the user clicks on the link element, the input element will be targeted and focused, and the styles specified in the :target:focus rule will be applied to it.
To find the kth closest element to a particular value in an array, we can use the following approach:
function findKthClosest(array, value, k) { const sortedArray = array.sort((a, b) => a - b); const index = sortedArray.indexOf(value); if (index === -1) { return null; } return sortedArray[index + k] || null; } const array = [1, 3, 5, 7, 9]; const value = 5; const k = 2; const result = findKthClosest(array, value, k); console.log(result); // 7
Let us now move up the ladder from intermediate to advanced. Listed below are a few interview questions for senior front end developers.
In React, data is passed from a parent component to a child component through props, which are short for "properties."
Props are a way for a parent component to pass data to its children, and for the children to receive and use that data. Props are passed to a child component as an object, and the child component can access the data within the object using the this.props property.
Here is an example of how a parent component might pass data to a child component using props:
import React from 'react'; // Parent component class Parent extends React.Component { render() { return ( <Child name="John" age={30} /> ); } } // Child component class Child extends React.Component { render() { return ( <p>Hello, my name is {this.props.name} and I am {this.props.age} years old.</p> ); } }
It is important to note that props are read-only, meaning that a child component cannot modify its props. If a child component needs to modify data that was passed to it via props, it should communicate this back to the parent component, which can then pass the updated data back down to the child via props. This is known as "props drilling"
One way for a child component to pass data back to its parent component is by using a callback function. A callback function is a function that is passed as a prop to the child component, and it is called by the child component when it needs to pass data back to the parent.
import React from 'react'; // Parent component class Parent extends React.Component { // Define a callback function that will be passed to the child component handleDataFromChild(data) { // Do something with the data passed from the child component } render() { return ( <Child onDataFromChild={this.handleDataFromChild} /> ); } } // Child component class Child extends React.Component { // When the child component needs to pass data back to the parent, it calls the callback function handleButtonClick() { this.props.onDataFromChild({ some: 'data' }); } render() { return ( <button onClick={this.handleButtonClick}>Send data to parent</button> ); } }
In this example, the parent component defines a callback function called handleDataFromChild, which it passes to the child component as a prop. The child component can then call this callback function whenever it needs to pass data back to the parent.
Another way for a child component to communicate data back to its parent is by using the React context API, or by using a state management library like Redux, which are typically only needed in larger applications with complex data flows and may not be necessary for smaller or simpler applications.
This is one of the frequently asked Front-end interview questions.
It is generally not recommended to call setState inside the render method of a React component. This is because render is called every time the component's state or props are updated, and calling setState inside render can cause an infinite loop.
For example, consider the following component:
class MyComponent extends React.Component { state = { count: 0, }; render() { this.setState({ count: this.state.count + 1 }); // Don't do this! return <div>{this.state.count}</div>; } }
In this component, render is called every time the component's state is updated. However, inside the render method, we are calling setState, which updates the state and triggers another call to render. This creates an infinite loop, causing the component to re-render constantly without ever stopping.
To avoid this issue, it is generally recommended to avoid calling setState inside the render method. Instead, setState should be called in response to user interactions like (clicking a button) or other events that trigger a state update.
Expect to come across this, one of the most popular front-end interview questions.
In a React application, a saga is a piece of code that is responsible for managing side effects. Side effects are actions that have an impact outside of the application, such as making a network request or interacting with a database.
Sagas are needed in React applications because side effects can often be complex and hard to manage, especially when they involve multiple steps or need to be coordinated with other actions in the application. By encapsulating side effects in a separate piece of code, called a saga, it becomes easier to manage and maintain the application.
Sagas are implemented using a library called redux saga, which is a middleware that sits between the React application and the Redux store. Redux-saga uses a combination of generator functions and an event-loop to manage side effects in a declarative and efficient way.
Below is an example of a simple saga that listens for a FETCH_USER action and makes a network request to fetch the user data:
import { takeEvery, call, put } from 'redux-saga/effects'; import api from '../api'; function* fetchUser(action) { try { const user = yield call(api.fetchUser, action.payload.userId); yield put({ type: 'FETCH_USER_SUCCESS', user }); } catch (error) { yield put({ type: 'FETCH_USER_ERROR', error }); } } function* watchFetchUser() { yield takeEvery('FETCH_USER', fetchUser); } export default watchFetchUser;
A reducer in Redux is a pure function that takes in the current state of the application, an action, and returns the next state of the application. There are no side effects associated with a pure function since it always returns the same output from the same input.
There are a few reasons why reducers are designed to be pure functions:
A must-know for anyone heading into the technical interview, this is one of the most frequently asked UI developer questions.
Redux is a state management library that is often used in React applications. It provides a simple and predictable way to manage the state of the application and to update the state in response to actions.
The basic flow of Redux can be summarized as follows:
Here is a simple example of a Redux flow in a React application:
// Action const action = { type: 'ADD_TODO', payload: { text: 'Learn Redux' } }; // Reducer function reducer(state, action) { switch (action.type) { case 'ADD_TODO': return { ...state, todos: [...state.todos, { text: action.payload.text }] }; default: return state; } } // Store const store = createStore(reducer, { todos: [] }); // Component class TodoList extends React.Component { render() { const { todos } = this.props; return ( <ul> {todos.map(todo => ( <li key={todo.text}>{todo.text}</li> ))} </ul> ); } } const mapStateToProps = state => ({ todos: state.todos }); const ConnectedTodoList = connect(mapStateToProps)(TodoList); // Dispatch action store.dispatch(action);
In this example, the ADD_TODO action is dispatched when the user clicks a button. The reducer processes the action and updates the todos array in the state. The store updates its internal state and the TodoList component re-renders to display the updated list of todos.
Redux flow is one of the most mentioned topics among Front-end developer questions, so make sure you master this topic as well.
In React, the lifecycle of a component refers to the different stages of its existence, from the moment it is created to the moment it is destroyed. In the past, React provided a set of lifecycle methods that could be used to manage the lifecycle of a component, such as componentDidMount, componentDidUpdate, and componentWillUnmount.
Starting from React 16.8, it is also possible to manage the lifecycle of a component using hooks. Hooks are functions that allow you to use state and other React features in functional components.
Below is an example of how to use the useEffect hook to manage the lifecycle of a component:
import { useEffect } from 'react'; function MyComponent() { useEffect(() => { // componentDidMount and componentDidUpdate return () => { // componentWillUnmount }; }); return <div>My component</div>; }
The useEffect hook takes a callback function as an argument, which will be called after the component is rendered. The callback function can perform side effects, such as making a network request or setting up an event listener.
The useEffect hook can also accept a second argument, which is an array of dependencies. If the dependencies change, the callback function will be called again. This allows you to specify when the effect should be run. If the array is empty, the effect will only be run once, when the component is mounted.
Here is an example of how to use the useEffect hook with dependencies:
import { useEffect, useState } from 'react'; function MyComponent() { const [count, setCount] = useState(0); useEffect(() => { console.log(`Count is ${count}`); // componentDidUpdate }, [count]); // Only re-run the effect if count changes return ( <div> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }
In React, the setState method is used to update the state of a component. It takes two arguments: the first argument is an object that specifies the state changes to be made, and the second argument is a callback function that will be called after the state has been updated.
Here is an example of how to use setState with a callback function:
class MyComponent extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } incrementCount = () => { this.setState({ count: this.state.count + 1 }, () => { console.log(`Count is now ${this.state.count}`); }); }; render() { return ( <div> <button onClick={this.incrementCount}>Increment</button> </div> ); } }
In this example, the incrementCount method updates the count state variable and logs the new value to the console using a callback function. The callback function is called after the state has been updated and the component has re-rendered.
The second argument to setState is optional, and you can omit it if you do not need to perform any actions after the state has been updated.
In a React application, a controlled component is a component that is controlled by the React state. This means that the component's value and behavior are determined by the state, and the component does not maintain its own internal state.
An uncontrolled component, on the other hand, is a component that maintains its own internal state. The value of the component is not controlled by the React state, and the component can update its own value independently of the React state.
Below is an example of a controlled text input component:
class ControlledInput extends React.Component { constructor(props) { super(props); this.state = { value: '' }; } handleChange = event => { this.setState({ value: event.target.value }); }; render() { return ( <input type="text" value={this.state.value} onChange={this.handleChange} /> ); } }
In this example, the value of the input is controlled by the value state variable, and the onChange event handler is used to update the state when the input value changes.
Below is an example of an uncontrolled text input component:
class UncontrolledInput extends React.Component { inputRef = React.createRef(); handleSubmit = event => { event.preventDefault(); console.log(this.inputRef.current.value); }; render() { return ( <form onSubmit={this.handleSubmit}> <input type="text" ref={this.inputRef} /> <button type="submit">Submit</button> </form> ); } }
In this example, the input does not have a value prop and is not controlled by the React state. Instead, the input's value is accessed directly using the ref system. When the form is submitted, the value of the input is logged to the console using the ref object.
Controlled components are generally easier to manage and test because the state of the component is fully determined by the React state. Uncontrolled components can be useful when you need to work with a DOM API or when you need to optimize performance by avoiding unnecessary re-renders.
A frequent occurrence in the list of Front-end developer technical interview questions, don't miss this one.
Generator functions are used in sagas because they provide a convenient way to pause and resume the execution of a function. This is useful when working with side effects, because it allows you to perform async operations in a declarative and efficient way.
In a saga, generator functions are used to manage the flow of the saga and to coordinate the execution of async tasks. The redux-saga library provides a set of helper functions, called effects, that can be used to pause the generator function and wait for a specific event to occur.
In HTML, a webpage can be displayed in either standards mode or quirks mode. These modes determine how a webpage is rendered by a web browser, and they can affect the way the webpage looks and behaves.
Standards mode is the preferred mode for rendering webpages, as it follows the standards set by the World Wide Web Consortium (W3C) for HTML, CSS, and other web technologies. When a webpage is displayed in standards mode, the web browser follows the standards specified in the HTML and CSS code, which ensures that the webpage is displayed consistently across different browsers.
Quirks mode, on the other hand, is a way for web browsers to handle older or improperly coded webpages. When a webpage is displayed in quirks mode, the web browser uses a different set of rules to try to display the webpage correctly. These rules are based on the way web browsers used to handle webpages in the past, and they can cause the webpage to be displayed differently in different browsers.
To determine which mode to use, web browsers look at the HTML code of the webpage and check for certain tags or attributes that indicate which mode to use.
For example, if the webpage includes a <!DOCTYPE> declaration at the top of the HTML code, the browser will use standards mode. If the <!DOCTYPE> declaration is missing or incorrect, the browser will use quirks mode.