Fullstack Interview
Fullstack Interview
Ans. Babel is a JavaScript compiler that converts modern JavaScript code into a version that is compatible with all
browsers. It is a free and open-source JavaScript transcompiler that converts ECMAScript 2015+ (ES6+) code into
backwards-compatible JavaScript code.
Babel allows web developers to take advantage of the newest features of the language. It enables React developers
to use the latest JavaScript syntax in their components.
Validating on submit ✔️ ✔️ ✔️
Field-level Validation ❌ ✔️ ✔️
dynamic inputs ❌ ✔️ 🤔
Controlled component: In a controlled component, the value of the input element is controlled by React. We store
the state of the input element inside the code, and by using event-based callbacks, any changes made to the input
element will be reflected in the code as well.
When a user enters data inside the input element of a controlled component, onChange function gets triggered and
inside the code, we check whether the value entered is valid or invalid. If the value is valid, we change the state and
re-render the input element with the new value.
function FormValidation(props) {
setInputValue([Link]);
};
return (
<div>
<form>
</div>
);
As one can see in the code above, the value of the input element is determined by the state of the inputValue
variable. Any changes made to the input element is handled by the updateInput function.
Uncontrolled component: In an uncontrolled component, the value of the input element is handled by the DOM
itself. Input elements inside uncontrolled components work just like normal HTML input form elements.
The state of the input element is handled by the DOM. Whenever the value of the input element is changed, event-
based callbacks are not called. Basically, react does not perform any action when there are changes made to the
input element.
Whenever use enters data inside the input field, the updated data is shown directly. To access the value of the input
element, we can use ref.
function FormValidation(props) {
[Link]();
};
return (
<div>
<form onSubmit={handleSubmit}>
<button type="submit">Submit</button>
</form>
</div>
);
As one can see in the code above, we are not using onChange function to govern the changes made to the input
element. Instead, we are using ref to access the value of the input element.
While React's PureComponent class provides this functionality for class components, for function components,
we can achieve the same behavior using [Link]().
• If the props are the same as the previous render, the component is not re-rendered.
Explanation:
• In the above example, the DisplayValue component is wrapped in [Link](), making it a
pure component.
• The [Link]() function checks whether the value prop has changed before re-rendering the
component.
– If the value prop is the same as the previous render, the component will not re-render.
– If the value prop has changed, the component will re-render and update its output
accordingly.
– If you pass primitive values like numbers, strings, or booleans, the shallow comparison checks
their equality.
– If you pass objects or arrays as props, [Link]() only checks if the reference to the
object or array has changed (not the values within them).
return (
<div>
<h1>Count: {count}</h1>
<button onClick={() => setCount(count + 1)}>Increment Count</button>
Explanation:
• In the ParentComponent, there's a count state that can be incremented, and a DisplayValue
component that shows the otherValue.
• Every time the count is incremented, the ParentComponent re-renders, but since the otherValue
prop is the same, DisplayValue will not re-render.
• For primitive values like numbers and strings, this is sufficient. But for complex objects like arrays and
objects, you should ensure that you pass new references when the data changes, or use a custom
comparison function.
javascript
export default [Link](DisplayValue, (prevProps, nextProps) => {
// Only re-render if the 'value' prop has changed
return [Link] === [Link];
});
Conclusion:
• A pure component in the context of function components can be created using [Link]().
• [Link]() is useful for optimizing performance, especially in cases where components receive
large props that do not change often.
This concept aligns with the same principles as pure components in class-based components, which are
implemented using [Link].
setTimeout(() => {
[Link]("Second Task")
setTimeout(() => {
[Link]("Third Task")
setTimeout(() => {
[Link]("Fourth Task")
}, 2000)
}, 2000)
}, 2000)
}, 2000)
To avoid callback hell and make the code more readable, you can use Promises and the async/await syntax. Here's
how you can refactor the code:
await delay(2000);
[Link]("First Task");
await delay(2000);
[Link]("Second Task");
await delay(2000);
[Link]("Third Task");
await delay(2000);
[Link]("Fourth Task");
};
executeTasks();
Q10. What is the difference between Traditional functions and Arrow functions?
Ans:
foo();
bar();
function foo() {
[Link]("I'm a foo()")
[Link]("I'm a bar()")
}// Function Expression: Loads only when the interpreter reaches this line
Traditional functions and arrow functions in JavaScript differ in several key aspects, particularly in how they handle
the this keyword, syntax, and use cases. Below are the major differences between them:
1. Syntax
• Traditional Function: The function is declared using the function keyword.
• Arrow Function: Uses the => syntax for a more concise function declaration.
Traditional Function Syntax:
javascript
function traditionalFunction() {
return "This is a traditional function";
}
javascript
const arrowFunction = () => "This is an arrow function";
2. Handling of this
The biggest difference between traditional and arrow functions is how they handle the this keyword.
• Traditional Functions:
– The value of this depends on how the function is called. If a function is called as a method of
an object, this refers to the object. Otherwise, this refers to the global object (window in
browsers).
– Inside a function defined using function, this will change based on context (e.g., it can be
bound dynamically, manually changed using bind(), call(), or apply()).
• Arrow Functions:
– Arrow functions lexically bind this. This means they inherit this from the context in which
they are defined, and it cannot be changed (even using bind(), call(), or apply()).
– This makes arrow functions useful for callbacks and methods where you need to ensure this
refers to the surrounding context.
Example of this in Traditional Function:
javascript
const obj = {
name: "Traditional",
getName: function () {
[Link]([Link]); // 'this' refers to obj
}
};
[Link](); // Output: "Traditional"
javascript
const obj = {
name: "Arrow",
getName: () => {
[Link]([Link]); // 'this' refers to the surrounding lexical scope
(probably undefined or window)
}
};
3. arguments Object
• Traditional Functions: The arguments object is available, which contains all the arguments passed to
the function.
• Arrow Functions: Arrow functions do not have their own arguments object. You would need to use
the rest operator ...args to achieve the same behavior.
Traditional Function Example:
javascript
function traditionalFunction() {
[Link](arguments); // 'arguments' contains all passed parameters
}
javascript
const arrowFunction = (...args) => {
[Link](args); // Must use rest parameter to capture arguments
};
4. Constructor Behavior
• Traditional Functions: Can be used as constructors (i.e., with the new keyword), meaning you can
create instances of traditional functions.
• Arrow Functions: Cannot be used as constructors. Attempting to use new with an arrow function will
throw an error.
Traditional Function Constructor Example:
javascript
function Person(name) {
[Link] = name;
}
const person = new Person('Alice');
[Link]([Link]); // Output: Alice
javascript
const Person = (name) => {
[Link] = name;
};
5. No prototype Property
• Traditional Functions: Have a prototype property, which allows them to be used with inheritance
patterns like function constructors.
• Arrow Functions: Do not have a prototype property, so they cannot be used in conjunction with
JavaScript’s prototype-based inheritance.
Example:
javascript
function Traditional() {}
const Arrow = () => {};
6. Use as Methods
• Traditional Functions: Can be used as methods within objects and have their own this context.
• Arrow Functions: Should not be used as methods inside objects where this refers to the object
itself, because this will not refer to the object as expected (it will refer to the surrounding scope).
Traditional Function Method Example:
javascript
const obj = {
name: "Traditional Method",
getName: function () {
[Link]([Link]); // 'this' refers to obj
}
};
javascript
const obj = {
name: "Arrow Method",
getName: () => {
[Link]([Link]); // 'this' refers to the outer scope, not the
object
}
};
[Link](); // Output: undefined (because 'this' does not refer to obj)
7. Function Hoisting
• Traditional Functions: Are hoisted, meaning they can be called before they are defined in the code.
• Arrow Functions: Are not hoisted. They must be defined before being invoked.
Traditional Function Hoisting Example:
javascript
sayHello();
function sayHello() {
[Link]("Hello from a traditional function!");
}
javascript
sayHello(); // Error: sayHello is not a function
Conclusion:
• Traditional functions provide more flexibility in terms of this binding and are suited for
constructors, object methods, and situations requiring dynamic this.
• Arrow functions are more concise, lexically bind this, and are typically used for short callbacks,
avoiding the need for manual this binding or boilerplate code. However, they are not suited for use
as object methods or constructors.
A Higher-Order Component is not a part of the React API, but it’s a pattern that emerges from React’s compositional
nature. HOCs are typically used for cross-cutting concerns, such as:
• Render hijacking
• Props manipulation
Characteristics of HOCs:
• HOCs take a component and return an enhanced component.
• They do not modify the original component but create a new one that wraps the original.
• HOCs are commonly used for tasks like authentication, conditional rendering, or handling
performance optimizations.
Syntax of an HOC:
javascript
const withExtraProps = (WrappedComponent) => {
return function EnhancedComponent(props) {
return <WrappedComponent {...props} newProp="Some value" />;
};
};
Explanation:
1. withLogging is the Higher-Order Component that takes WrappedComponent as an argument.
2. Inside withLogging, we return a new functional component, EnhancedComponent, which logs the
props to the console and renders the original WrappedComponent (DisplayData in this case) with
the passed props.
3. The original component (DisplayData) is wrapped by withLogging to create
DisplayDataWithLogging, which logs the props every time it's rendered.
Explanation:
1. withConditionalRendering is the Higher-Order Component that checks if the isVisible prop
is true or false.
2. Separation of Concerns: HOCs help decouple business logic from UI components. You can focus on
building reusable, presentational components while keeping logic in HOCs.
3. Prop Manipulation: HOCs can modify or enhance the props passed to the wrapped component,
allowing you to abstract away details or inject additional data.
Conclusion:
Higher-Order Components (HOCs) in React offer a powerful pattern for code reuse by enhancing components with
additional logic. By wrapping a component, you can add new behaviors, like logging props, conditional rendering, or
handling authentication, without modifying the original component.
When a web page hosted on one domain makes a request to a server on a different domain, the browser enforces
the Same-Origin Policy by default, which restricts such cross-origin requests. CORS is a mechanism that relaxes this
restriction under controlled conditions, allowing servers to declare which origins are permitted to access their
resources.
Let's assume you have a web page hosted at [Link] and it needs to make a request to an API hosted at
[Link]
Server-Side Configuration:
On the server hosting the API ([Link] the server needs to include the appropriate CORS
headers in its responses. This is typically done by adding headers like Access-Control-Allow-Origin to specify which
origins are allowed to access the resources.
Access-Control-Allow-Origin: [Link]
This header tells the browser that requests from [Link] are allowed.
Client-Side Request:
On the client side, when making a request from the web page ([Link] to the API
([Link] the browser checks if the server's CORS headers allow the request. If the server
permits the origin (via the Access-Control-Allow-Origin header), the browser allows the request; otherwise, it blocks
the request.
fetch('[Link]
The browser, before allowing the request, checks the CORS headers in the server's response.
It's important to note that CORS is a browser security feature and does not affect non-browser environments like
server-to-server communication. Additionally, the specific CORS headers and configurations may vary depending on
the server technology being used (e.g., Express for [Link], Apache, etc.).
bash
npm install redux react-redux
javascript
// [Link]
import { createStore } from 'redux';
import reducer from './reducer'; // Your reducer
3. Define Reducer(s):
Reducers specify how the application's state changes in response to actions sent to the store.
javascript
// [Link]
const initialState = {
counter: 0,
};
javascript
// [Link]
export const increment = () => ({
type: 'INCREMENT',
});
javascript
// [Link]
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import store from './store'; // Redux store
import App from './App';
[Link](
<Provider store={store}>
<App />
</Provider>,
[Link]('root')
);
javascript
// [Link]
import React from 'react';
import { connect } from 'react-redux';
import { increment, decrement } from './actions';
const Counter = ({ counter, increment, decrement }) => {
return (
<div>
<h2>Counter: {counter}</h2>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
</div>
);
};
try {
const response = await
fetch('[Link]
const data = await [Link]();
dispatch({ type: 'FETCH_SUCCESS', payload: data });
} catch (error) {
dispatch({ type: 'FETCH_ERROR', error });
}
};
};
4. Modify the Reducer to Handle Async Actions:
javascript
// [Link]
const initialState = {
data: null,
loading: false,
error: null,
};
2. For async operations, you would typically handle them outside Redux (in components or
services).
2. With Thunk:
2. You can dispatch asynchronous actions and make API calls directly from Redux action creators,
keeping the logic centralized.
Summary:
• Without Thunk: Redux handles synchronous state updates. You dispatch actions, and the reducer
updates the state accordingly.
• With Thunk: You can perform asynchronous tasks (like API calls) in your action creators and dispatch
multiple actions based on the result, such as success or error handling.
This pattern improves the scalability of the application, particularly when dealing with complex asynchronous
workflows in Redux.
Syntax of an IIFE:
javascript
(function() {
// Code inside the function
[Link]("This is an IIFE");
})();
Detailed Breakdown:
1. Function Expression: The function is wrapped in parentheses to ensure it is treated as an expression
rather than a declaration.
2. Invocation: The () at the end immediately calls the function after it is defined.
Use Cases for IIFE:
1. Avoiding Global Scope Pollution: Variables and functions inside an IIFE are not accessible outside of
it, preventing them from cluttering the global scope.
javascript
(function() {
var privateVariable = "I am private";
[Link](privateVariable); // Accessible inside
})();
2. Creating a Local Scope: In the pre-ES6 era, JavaScript did not have block-level scope (e.g., let and
const didn't exist), so IIFEs were used to create local scopes.
javascript
(function() {
for (var i = 0; i < 5; i++) {
// `i` is scoped only to this IIFE
}
})();
3. Avoiding Conflicts in Global Namespace: If multiple scripts use common variable names, IIFEs can
prevent conflicts by keeping variables local to each script.
javascript
(function() {
var version = "1.0.0";
[Link]("Script 1 version:", version);
})();
(function() {
var version = "2.0.0";
[Link]("Script 2 version:", version);
})();
javascript
(function(name) {
[Link]("Hello, " + name);
})("John");
javascript
(() => {
[Link]("IIFE with arrow function");
})();
Conclusion:
IIFEs are a useful pattern in JavaScript for encapsulating code, creating private variables, and avoiding global
namespace pollution. They are particularly handy in legacy code or situations where variable scoping and privacy are
crucial. However, with the advent of ES6 modules and block-scoped variables (let and const), IIFEs are less
commonly used but still relevant in certain contexts.
function MyComponent() {
return (
<div>
</div>
);
function App() {
return (
<ErrorBoundary FallbackComponent={ErrorFallback}>
<MyComponent />
</ErrorBoundary>
);
}
export default App;
In the example above, the ErrorBoundary component from react-error-boundary is used to wrap the component
(MyComponent) that might throw an error. The ErrorFallback component is rendered if an error occurs, providing a
way to handle and display the error. The resetErrorBoundary function allows the user to attempt to recover from the
error.
call Method:
The call method is used to invoke a function with a specified this value and individual arguments.
function greet(message) {
[Link](`${message}, ${[Link]}`);
[Link](person, 'Hello');
apply Method:
The apply method is similar to call but accepts an array-like object as the second argument, where each element in
the array corresponds to an argument of the function.
function greet(message) {
[Link](`${message}, ${[Link]}`);
}
const person = { name: 'Jane' };
[Link](person, ['Hi']);
bind Method:
The bind method returns a new function with a specified this value and, optionally, initial arguments.
Unlike call and apply, bind does not immediately invoke the function; it returns a new function that can be invoked
later.
function greet(message) {
[Link](`${message}, ${[Link]}`);
greetPerson('Hola');
REST:
1. Data Fetching:
In REST, each endpoint represents a specific resource, and you request the resource with an HTTP method (GET,
POST, PUT, DELETE, etc.).
Different endpoints are used for different views or representations of the data.
2. Data Shape:
The shape of the response is predefined by the server. Clients receive a fixed structure, and any additional or missing
data requires a new endpoint or modification on the server.
Under-fetching: Not getting enough data in a single request, requiring additional requests.
GraphQL:
1. Data Fetching:
In GraphQL, clients specify the shape and structure of the response they need. The client sends a query to the server,
and the server responds with exactly the requested data.
2. Data Shape:
The client defines the structure of the response using the GraphQL query language. The server returns data in the
same structure as requested.
GraphQL eliminates over-fetching and under-fetching because clients request only the data they need.
1. Implicit Binding:
Implicit binding occurs when a function is called as a method of an object. In this case, ‘this’ is implicitly set to the
object that owns the method.
const person = {
name: 'John',
greet: function() {
};
In this example, when [Link]() is called, this is implicitly bound to the person object.
2. Explicit Binding:
Explicit binding occurs when the this value is explicitly set using methods like call(), apply(), or bind().
Synthetic Events
In React, synthetic events are JavaScript objects that encapsulate the browser's native event. They are created by
React when a native event occurs, such as a click, key press, or mouseover. These synthetic events provide a
consistent interface across different browsers, ensuring that your React components can handle events without
worrying about browser compatibility.
• Cross-browser compatibility: Synthetic events abstract away the differences between browser
implementations, making it easier to write consistent event handlers.
• Immutability: Synthetic events are immutable, meaning their properties cannot be modified after
they are created. This helps prevent unintended side effects.
• Event bubbling and capturing: Synthetic events support the standard event propagation mechanisms
of bubbling and capturing.
• Additional properties: Synthetic events have additional properties specific to React, such as target,
currentTarget, preventDefault(), and stopPropagation(), which can be used to
manipulate and control event behavior.
Example: Creating a Click Event Handler
Here's a React component that demonstrates how to create a click event handler using synthetic events:
javascript
import React, { useState } from 'react';
function MyComponent() {
const [count, setCount] = useState(0);
return (
<div onClick={handleClick}>
<p>Clicked: {count}</p>
</div>
);
}
In this example:
3. The onClick prop is attached to the div element, passing the handleClick function as its value.
4. When the div is clicked, the handleClick function is called with a synthetic event object as its
argument.
5. Inside the handleClick function, we can access various properties of the synthetic event object,
such as [Link], which refers to the clicked element.
Key Points:
• You can access various properties of synthetic events to get information about the event and
manipulate its behavior.
• Synthetic events provide a consistent and cross-browser compatible way to handle events in React.
By understanding synthetic events and how to use them effectively, you can create more robust and interactive React
applications.
To create a portal, call createPortal, passing some JSX, and the DOM node where it should
be rendered:
import { createPortal } from 'react-dom';
// ...
<div>
<p>This child is placed in the parent div.</p>
{createPortal(
<p>This child is placed in the document body.</p>,
[Link]
)}
</div>
• Relative unit: The em unit is relative to the font size of the element's parent.
• Dynamic: The size of an element using em units will change if the parent's font size changes.
• Example:
css
.element {
font-size: 1.2em;
}
If the parent element has a font size of 16px, the .element will have a font size of 19.2px (16px * 1.2). If the
parent's font size changes, the .element's font size will also adjust accordingly.
rem:
• Relative unit: The rem unit is relative to the root element's (usually the <html> element) font size.
• Static: The size of an element using rem units will remain constant regardless of changes to the
parent's font size.
• Example:
css
html {
font-size: 16px;
}
.element {
font-size: 1.2rem;
}
In this example, the .element will always have a font size of 19.2px, regardless of the font size of its parent
elements.
Key Differences:
• Relative to: em is relative to the parent's font size, while rem is relative to the root element's font size.
• Dynamic vs. Static: em units are dynamic and change with the parent's font size, while rem units are
static and remain constant.
• Use Cases: em units are often used for creating responsive layouts, where the font size of child
elements scales proportionally to the parent. rem units are typically used for setting base font sizes
and creating consistent typography throughout a website.
Choosing the Right Unit:
The choice between em and rem depends on your specific needs and design goals. If you want to create a responsive
layout where the font sizes scale proportionally to the parent element, em units are a good choice. If you want to
establish a consistent base font size that remains unchanged throughout the website, rem units are more suitable.
• Purpose: Provides information about the browser environment and allows you to interact with it.
• Functionality: Accessing browser properties, manipulating the browser window, navigating history,
and interacting with the user.
Document Object Model (DOM):
• Purpose: Represents the HTML document as a tree structure of objects, providing a way to access and
manipulate its content, structure, and style.
• Functionality: Creating, modifying, and removing HTML elements, accessing and setting element
attributes and styles, and handling events.
Key Differences:
Functionality Browser properties, window manipulation, DOM manipulation, element access, attribute and
history navigation, user interaction style modification, event handling
Example:
javascript
// BOM Example:
[Link]("Browser Window Width:", [Link]);
[Link](); // Go back to the previous page
// DOM Example:
const paragraph = [Link]("p");
[Link] = "This is a new paragraph.";
[Link](paragraph);
const heading = [Link]("myHeading");
[Link] = "red";
[Link] = "Modified Heading";
In this example:
• The first line uses the BOM to access the browser window width.
• The remaining lines use the DOM to create a new paragraph element, append it to the document
body, and modify the style and content of an existing heading element.
In summary:
• The BOM provides a way to interact with the browser environment, while the DOM provides a way to
manipulate the HTML document.
• Both are essential for creating dynamic and interactive web applications.
1. Capture phase: The event starts at the outermost element and travels down to the target element.
2. Target phase: The event reaches the target element (the element where the event originated).
3. Bubbling phase: The event travels back up from the target element to the outermost element.
Example:
html
<div id="outer">
<div id="middle">
<button id="inner">Click me</button>
</div>
</div>
javascript
const outerDiv = [Link]('outer');
const middleDiv = [Link]('middle');
const innerButton = [Link]('inner');
In this example:
1. When the innerButton is clicked, the click event first propagates down from the outerDiv to
the middleDiv and then to the innerButton (capture phase).
3. The click event bubbles up from the innerButton to the middleDiv and then to the outerDiv
(bubbling phase).
If you click on the innerButton, the following will be logged to the console:
• Event delegation: Attaching an event handler to a parent element and handling events for its children
to improve performance.
• Custom event propagation: Creating your own event propagation mechanisms for specific use cases.
I'd be glad to explain the difference between event bubbling and event capturing in JavaScript, along with examples:
Event Bubbling:
• Definition: Event bubbling is the process by which events propagate up the DOM hierarchy from the
target element to its parent elements.
• Flow: When an event occurs on an element, it's first handled by that element, and then it's
propagated to its parent element, and so on until it reaches the outermost element.
• Example:
html
<div id="outer">
<div id="middle">
<button id="inner">Click me</button>
</div>
</div>
javascript
const outerDiv = [Link]('outer');
const middleDiv = [Link]('middle');
const innerButton = [Link]('inner');
In this example, if you click on the innerButton, the following will be logged to the console:
• Definition: Event capturing is the process by which events propagate down the DOM hierarchy from
the outermost element to the target element.
• Flow: When an event occurs on an element, it's first handled by the outermost element, and then it's
propagated to its child elements until it reaches the target element.
• Example:
javascript
[Link]('click', (event) => {
[Link]('Outer div clicked (capturing)');
[Link]();
}, true);
In this example, if you click on the innerButton, the following will be logged to the console:
• Direction: Event bubbling propagates up the DOM hierarchy, while event capturing propagates down.
• Order: In event bubbling, the target element is handled first, followed by its parent elements. In event
capturing, the outermost element is handled first, followed by its child elements.
• Use Case: Event bubbling is more commonly used, especially for event delegation. Event capturing is
less common and is typically used for specific scenarios where you need to handle events before they
reach the target element.
By understanding the difference between event bubbling and event capturing, you can effectively handle events in
your JavaScript applications and create more robust and interactive user interfaces.
The third argument to addEventListener() determines whether an event will bubble or capture:
• false (default): The event will bubble up from the target element to its parent elements.
• true: The event will capture down from the outermost element to the target element.
javascript
const outerDiv = [Link]('outer');
const middleDiv = [Link]('middle');
const innerButton = [Link]('inner');
// Bubbling
[Link]('click', (event) => {
[Link]('Inner button clicked (bubbling)');
});
// Capturing
[Link]('click', (event) => {
[Link]('Outer div clicked (capturing)');
[Link](); // Prevent further propagation
}, true);
In this example:
• The first three event listeners use the default false argument, so the events will bubble up.
• The last three event listeners use the true argument, so the events will capture down.
When you click on the innerButton, you'll see that the events are handled in different orders depending on
whether they are bubbling or capturing.
Q 36. [Link], [Link], [Link], [Link]?
Ans. [Link]
Q 37. for-of vs for-in array?
Ans. [Link]
a106612cb49
Ans. I'd be glad to explain the differences between for...of and for...in loops in JavaScript, along with
examples:
for...of Loop:
• Purpose: Iterates over the values of iterable objects, such as arrays, strings, and objects with a
[Link] method.
• Syntax:
javascript
for (let value of iterable) {
// Code to be executed for each value
}
• Example:
javascript
const fruits = ['apple', 'banana', 'orange'];
apple
banana
orange
for...in Loop:
• Syntax:
javascript
for (let property in object) {
// Code to be executed for each property
}
• Example:
javascript
const person = { name: 'Alice', age: 30, city: 'New York' };
name Alice
age 30
city New York
Key Differences:
• Iteration: for...of iterates over values, while for...in iterates over properties.
• Iterable Objects: for...of works with iterable objects (arrays, strings, etc.), while for...in works
with objects.
• Order: The order of iteration for for...in is not guaranteed, while for...of iterates in the order
of the iterable object's elements.
Choosing the Right Loop:
• Use for...of when you need to iterate over the values of an iterable object.
• Use for...in when you need to iterate over the properties of an object.
Additional Notes:
• Be aware that for...in can iterate over inherited properties, which might not be desirable in all
cases.
• If you need to modify the values of an array while iterating over it, consider using a for loop or the
forEach() method instead of for...of.
By understanding the differences between for...of and for...in loops, you can choose the appropriate loop
for your specific use cases and write more efficient and readable JavaScript code.
1. Temporary Replacement: Stubs replace parts of the code that interact with external dependencies, such as
other modules, databases, or APIs.
2. Controlled Behavior: Stubs allow you to control the behavior of dependencies, making it easier to test
different scenarios without relying on the actual external systems.
3. Isolation: By using stubs, you can isolate the code being tested, ensuring that the test focuses only on its
logic without being affected by external factors.
For example, suppose you have a function that fetches data from an external API. Instead of actually making requests
to the API during testing, you can create a stub that simulates the API's behavior and returns predefined responses.
This allows you to test how your function handles different responses without relying on the actual API.
In [Link], there are various libraries and techniques for creating stubs, including manual stubbing with [Link] or
using mock libraries like Jest's built-in mocking capabilities. These tools provide convenient ways to create stubs and
verify the behavior of your code during testing.
Let's say we have a module that fetches data from an external API using the axios library, and we want to test a
function that depends on this API call.
// [Link]
try {
return [Link];
} catch (error) {
throw error;
[Link] = { fetchDataFromAPI };
Now, let's create another module called [Link], which contains a function that processes the data fetched
from the API:
// [Link]
try {
return data;
} catch (error) {
throw error;
[Link] = { processData };
To test the processData function without actually making HTTP requests to the external API, we can use a stub.
Here's an example test file using Jest:
// [Link]
describe('processData', () => {
});
});
Ans:
The above method is synchronous method of writing on a file.
Ans.
File beginning… and File Ending… are immediately executed as they are synchronous tasks.
The others are put inside a call stack and get executed from there as per the precedence.
Q 46. DOM
Ans [Link]
Q 47. What is Closure?
Ans. This means that a function defined inside another function has access to the variables
and parameters of its outer function, even after the outer function has finished executing.
function outerFunction() {
var outerVariable = 'I am from outerFunction';
function innerFunction() {
[Link](outerVariable); // innerFunction has access to outerVariable
}
Hoisting in Functions
Hoisting in JavaScript refers to the process where function declarations are moved to the top of their scope (either
global or function scope) before the code is executed. This means that you can call a function before it's declared,
and the interpreter will still be able to find it.
Example:
javascript
function greet() {
[Link]("Hello, world!");
}
In this example:
2. The function call greet() is executed before the function declaration, but it still works because the
function has been hoisted.
3. The [Link](greet) statement prints the greet function itself, showing that it has been
hoisted and is accessible.
Important Notes:
• Function expressions are not hoisted: Only function declarations are hoisted. Function expressions
are not moved to the top of the scope and must be declared before they are used.
• Hoisting is not initialization: Hoisting moves the declaration to the top, but it doesn't initialize the
function's variables or body.
• Scope matters: Hoisting occurs within the scope where the function is defined. If a function is defined
inside a function, it will be hoisted within that inner scope.
Example with Function Expressions:
javascript
greet(); // Output: ReferenceError: greet is not defined
In this case, the greet function expression is not hoisted, so calling it before it's declared results in a
ReferenceError.
Understanding Hoisting:
Hoisting is a useful concept to understand in JavaScript, as it helps explain how functions can be called before they
are declared. However, it's important to use hoisting carefully and avoid relying on it for code organization. It's
generally considered best practice to declare functions before using them to improve code readability and
maintainability.
1. constructor(props)
The constructor is a special method used to initialize a newly created object, including the state and any other
initialization logic. In the context of a React class component, it's where you usually initialize the component's state.
• Why use constructor? The constructor allows you to initialize the component's state with
[Link] = { ... }. In your code, you're setting title to 'Init' in the constructor:
js
[Link] = { title: 'Init' };
• Props handling: The constructor in React takes props as a parameter so you can access
[Link] in the component. While not directly used in your example, it is important when you
want to work with props within the constructor.
2. super(props)
The super keyword is required when you extend a class, in this case, [Link]. It calls the constructor
of the parent class ([Link]) and allows you to access this inside the constructor.
• Why call super(props)? You must call super(props) before accessing this in the constructor. If
you don't, JavaScript will throw an error, as the parent class ([Link]) needs to be
initialized first.
By passing props to super, you allow the parent class to receive the props as well:
js
super(props);
Without super, you won't have access to [Link] within the constructor.
To Summarize:
• constructor(props): Initializes the component's state and binds methods. It takes props to use
them inside the component.
• super(props): Calls the parent class's constructor and gives you access to this and [Link].
It must be called before using this inside the constructor.
In modern React, if you are not using the constructor for any specific logic (like state initialization or method binding),
you can omit it entirely, since [Link] can be initialized directly as a class property.
js
import React, { useEffect, useState } from 'react';
useEffect(() => {
[Link]('This runs after every render');
});
return (
<div>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};
js
useEffect(() => {
[Link]('This runs only once after the component mounts');
}, []);
js
useEffect(() => {
[Link]('This runs when count changes');
}, [count]); // Only runs when `count` changes
js
useEffect(() => {
const intervalId = setInterval(() => {
[Link]('Running every second');
}, 1000);
return () => {
clearInterval(intervalId); // Cleanup when component unmounts
};
}, []); // Empty array ensures it runs only once (on mount and unmount)
return () => {
[Link](`Unsubscribed from user with ID: ${userId}`);
};
}, [userId]); // Effect runs when `userId` changes
js
useEffect(() => {
const fetchData = async () => {
const result = await fetch('[Link]
const data = await [Link]();
[Link](data);
};
fetchData();
}, []); // Only run once on mount
js
useEffect(() => {
[Link]('Effect for count');
}, [count]);
useEffect(() => {
[Link]('Effect for userId');
}, [userId]);
js
useEffect(() => {
const timeoutId = setTimeout(() => {
[Link]('Debounced input:', inputValue);
}, 500);
return () => {
clearTimeout(timeoutId); // Cleanup timeout on each input change
};
}, [inputValue]); // Runs only when `inputValue` changes
Summary:
• No dependency array: Runs on every render.
• Empty dependency array []: Runs only once after the component mounts.
• Specific dependencies [state]: Runs when the specified state or prop changes.
• Return function: Acts as a cleanup function, useful for unmounting or before re-running the effect.
Each use case provides a different lifecycle behavior for functional components, making useEffect versatile and
powerful for handling side effects in React.
1. Installation
To use React Router, first, install the react-router-dom package:
bash
npm install react-router-dom
2. Basic Setup
Start by setting up the Router component to wrap your entire app. This enables routing throughout your
application.
jsx
import React from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
Key Components:
• <Router>: The BrowserRouter component wraps the entire app and allows routing.
• <Routes>: Contains all your route definitions (replaces the old Switch component in React Router
v6).
• <Route>: Defines a specific route path and the component to render when that path is visited.
jsx
import { Link } from 'react-router-dom';
jsx
import { useParams } from 'react-router-dom';
// In the routes
<Route path="/user/:id" element={<UserProfile />} />
jsx
import { useNavigate } from 'react-router-dom';
6. Nested Routes
React Router supports nested routing, where a parent component renders child components based on sub-paths.
jsx
const Dashboard = () => (
<div>
<h2>Dashboard</h2>
<Routes>
<Route path="settings" element={<Settings />} />
<Route path="profile" element={<Profile />} />
</Routes>
</div>
);
jsx
import { Navigate } from 'react-router-dom';
// Usage
<Route path="/dashboard" element={<PrivateRoute
isAuthenticated={userLoggedIn}><Dashboard /></PrivateRoute>} />
9. Query Parameters
React Router does not provide built-in query string parsing, but you can handle it using useLocation.
jsx
import { useLocation } from 'react-router-dom';
Example Application
Below is a full example demonstrating multiple features of React Router:
jsx
import React from 'react';
import { BrowserRouter as Router, Route, Routes, Link, useParams, Navigate,
useNavigate } from 'react-router-dom';
// Components
const Home = () => <h2>Home</h2>;
const About = () => <h2>About</h2>;
return (
<Router>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
<Link to="/user/1">User Profile</Link>
<Link to="/dashboard">Dashboard</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/user/:id" element={<UserProfile />} />
<Route path="/dashboard" element={<PrivateRoute
isAuthenticated={isAuthenticated}><Dashboard /></PrivateRoute>} />
<Route path="*" element={<NotFound />} />
</Routes>
</Router>
);
};
Summary:
• <Router>: Wraps your app to enable routing.
• <Routes> and <Route>: Define the different routes and which components to render.
This setup gives you everything you need to build a basic to advanced routing system in your React app!
Q 62. How to pass data between sibling components using React router?
Ans. Passing data between sibling components in React can be achieved in a few ways, but when you're using React
Router, one effective way is through URL parameters, query parameters, or shared state via a parent component.
Here's how you can handle this:
Example:
jsx
import React, { useState } from 'react';
import { BrowserRouter as Router, Route, Routes, Link } from 'react-router-
dom';
<Routes>
<Route path="/sibling1" element={<Sibling1 sharedData={sharedData}
setSharedData={setSharedData} />} />
<Route path="/sibling2" element={<Sibling2
sharedData={sharedData} />} />
</Routes>
</Router>
</div>
);
};
In this example:
• Parent holds the state (sharedData) and passes it down to both Sibling1 and Sibling2 as
props.
• Sibling1 can update the shared data using the setSharedData function, which will automatically
update Sibling2 since the state is shared.
Example:
jsx
import React from 'react';
import { BrowserRouter as Router, Route, Routes, Link, useNavigate,
useParams } from 'react-router-dom';
return (
<div>
<h2>Sibling 1</h2>
<button onClick={handlePassData}>Pass Data to Sibling 2</button>
</div>
);
};
return (
<div>
<h2>Sibling 2</h2>
<p>Received Data: {data}</p>
</div>
);
};
<Routes>
<Route path="/sibling1" element={<Sibling1 />} />
<Route path="/sibling2/:data" element={<Sibling2 />} />
</Routes>
</Router>
);
};
In this example:
• Sibling2 accesses that data using the useParams hook from React Router.
Example:
jsx
import React from 'react';
import { BrowserRouter as Router, Route, Routes, Link, useNavigate,
useLocation } from 'react-router-dom';
return (
<div>
<h2>Sibling 1</h2>
<button onClick={handlePassData}>Pass Data to Sibling 2</button>
</div>
);
};
return (
<div>
<h2>Sibling 2</h2>
<p>Received Data: {data}</p>
</div>
);
};
<Routes>
<Route path="/sibling1" element={<Sibling1 />} />
<Route path="/sibling2" element={<Sibling2 />} />
</Routes>
</Router>
);
};
In this example:
• Sibling2 uses useLocation and URLSearchParams to extract and display the query parameter.
// Create a context
const DataContext = createContext();
return (
<[Link] value={{ sharedData, setSharedData }}>
<Router>
<nav>
<Link to="/sibling1">Sibling 1</Link>
<Link to="/sibling2">Sibling 2</Link>
</nav>
<Routes>
<Route path="/sibling1" element={<Sibling1 />} />
<Route path="/sibling2" element={<Sibling2 />} />
</Routes>
</Router>
</[Link]>
);
};
return (
<div>
<h2>Sibling 1</h2>
<p>Data from Context: {sharedData}</p>
<input
type="text"
value={sharedData}
onChange={(e) => setSharedData([Link])}
/>
</div>
);
};
return (
<div>
<h2>Sibling 2</h2>
<p>Data from Context: {sharedData}</p>
</div>
);
};
In this example:
• The DataContext provides the shared state.
• Both Sibling1 and Sibling2 consume the shared state using useContext.
Conclusion:
• Shared Parent State: The most common method for sharing data between siblings.
• Context API: Ideal for sharing global state across multiple components without needing to pass props
manually.
Each of these methods has its use case, depending on how persistent or dynamic the data is, and how closely related
the components are.
• useLayoutEffect: Runs synchronously after the DOM has been updated but before the browser
has painted the changes. This makes it useful for operations that need to happen before the screen is
rendered to avoid flickering or incorrect measurements.
• Measuring DOM elements: When you need to calculate dimensions, positions, or other layout-related
properties of DOM elements.
• Synchronous visual updates: When you need to make visual changes (e.g., applying animations) that
must happen before the screen is repainted to avoid layout shift or flickering.
• Fixing race conditions: If using useEffect causes visible flicker or incorrect layout, switching to
useLayoutEffect may help ensure the DOM updates are handled synchronously.
jsx
import React, { useLayoutEffect, useRef, useState } from 'react';
useLayoutEffect(() => {
// Measure the width of the element
if ([Link]) {
setWidth([Link]);
}
}, []); // Empty dependency array ensures it runs once after mount
return (
<div>
<div ref={divRef} style={{ width: '50%' }}>
I'm a div with 50% width of the parent.
</div>
<p>Measured width: {width}px</p>
</div>
);
};
In this example:
• useLayoutEffect is used to measure the width of the div before the browser renders it to avoid
layout shifts.
• The effect runs synchronously, ensuring that the measured width is accurate and no flickering occurs.
• Non-visual side effects: If your effect doesn't directly affect the layout or need to happen before the
browser renders, it's better to use useEffect, which is asynchronous and non-blocking.
• Avoiding flicker: If rendering is causing visual flickering or incorrect placement when using
useEffect, you may need to switch to useLayoutEffect to ensure synchronous updates.
• Animations: If you're applying animations or transitioning between different states and want to
prevent layout shifts, you might use useLayoutEffect.
Summary:
• useLayoutEffect is useful when you need to perform DOM-related calculations (like measuring
size) before the browser paints.
• It runs synchronously, blocking rendering until the effect finishes, unlike useEffect, which runs
asynchronously after the paint.
• Use it carefully to avoid performance issues, and only when dealing with layout changes that need to
happen before rendering.
In most cases, useEffect is preferred for asynchronous effects, but useLayoutEffect is your go-to when
layout-related changes need to happen immediately.
React lifecycle hooks will have the methods that will be automatically called at
different phases in the component lifecycle and thus it provides good control over
what happens at the invoked point. It provides the power to effectively control and
manipulate what goes on throughout the component lifecycle.
For example, if you are developing the YouTube application, then the application will
make use of a network for buffering the videos and it consumes the power of the
battery (assume only these two). After playing the video if the user switches to any
other application, then you should make sure that the resources like network and
battery are being used most efficiently. You can stop or pause the video buffering
which in turn stops the battery and network usage when the user switches to
another application after video play.
So we can say that the developer will be able to produce a quality application with
the help of lifecycle methods and it also helps developers to make sure to plan what
and how to do it at different points of birth, growth, or death of user interfaces.
To implement route-based lazy loading, we use [Link]() to dynamically import the components and
Suspense to provide a fallback while the components are being loaded.
Breakdown:
1. Lazy Loading Components:
js
const HomePage = [Link](() => import('./HomePage'));
const AboutPage = [Link](() => import('./AboutPage'));
const ContactPage = [Link](() => import('./ContactPage'));
2. Suspense Fallback:
1. Suspense is used to show a fallback UI (like a loading spinner) while the lazy-loaded
component is being fetched. It wraps the Routes component in this case.
js
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/about" element={<AboutPage />} />
<Route path="/contact" element={<ContactPage />} />
</Routes>
</Suspense>
1. The Router component handles the application's routing, and the Routes component
contains the individual Route components. Each Route specifies a path and the component
to render lazily.
• Improved User Experience: The app loads faster because users only download the necessary code for
the current route, and additional code is loaded on demand.
static getDerivedStateFromError(error) {
return { hasError: true };
}
render() {
if ([Link]) {
return <div>Something went wrong while loading the page.</div>;
}
return [Link];
}
}
This ensures that if any error occurs while loading the component, the ErrorBoundary will catch it and display an
error message instead of breaking the entire app.
By using route-based lazy loading, you make your app more scalable, especially for large applications where not all
routes need to be loaded at once. This helps in improving both performance and user experience.
css
/* [Link] */
.container {
background-color: lightblue;
padding: 20px;
}
.text {
color: red;
font-size: 20px;
}
jsx
import React from 'react';
import './[Link]'; // Importing global CSS
• No Isolation: Since the styles are global, you need to be careful with class names to avoid conflicts.
2. CSS Modules (Scoped CSS)
CSS Modules offer a way to scope styles to a specific component. When you use a CSS module, the classes are locally
scoped by default, which prevents class name collisions. CSS Modules automatically generate unique class names
during the build process.
css
/* [Link] */
.container {
background-color: lightgreen;
padding: 20px;
}
.text {
color: blue;
font-size: 25px;
}
jsx
import React from 'react';
import styles from './[Link]'; // Importing CSS Module
• Dynamic Class Names: The class names are transformed into unique strings during the build process,
ensuring no collision occurs, even if multiple components use the same class names.
• Cleaner Code: You can reuse common class names (container, text, etc.) without worrying about
conflicts.
Output Example:
• If you're using Global CSS, both .container and .text classes are applied globally. If another
component has classes with the same names, they will affect each other.
• If you're using CSS Modules, each component will have its own unique class names, so .container
in [Link] will only affect that component. Even if another component has a .container
class in its own module, they will not conflict.
Class Name Possible if the same class names are used in Avoided by unique, dynamically generated class
Collisions different files names
Ease of Use Simple and familiar for smaller projects Slightly more complex setup (need to import
styles as objects)
Reusability Classes can be reused across components Classes are component-scoped, harder to reuse
globally
Maintainability Can lead to conflicts in large projects Better suited for large-scale projects with many
components
Conclusion:
• Global Stylesheet: Useful for small projects or when you want to apply global styles. However, you
need to manage class names carefully to avoid conflicts.
• CSS Modules: Ideal for large-scale projects or when you want to ensure that styles are isolated to
specific components, avoiding conflicts or unintentional overrides. They help keep the code more
modular and maintainable.
bash
npm install dynamoose
2. Define Your DynamoDB Model: Define your model by creating a schema using Dynamoose. For
example, assume you have a User model.
javascript
const dynamoose = require('dynamoose');
3. Perform a Parallel Scan: The key to using a parallel scan in Dynamoose is the parallel option. You
need to specify two options: totalSegments (the total number of segments to divide the scan into)
and segment (the segment to scan). The parallel option ensures the scan is divided and executed
in parallel.
Below is an example of a parallel scan with 4 segments:
javascript
const totalSegments = 4; // Total number of segments to divide the scan
const promises = [];
2. segment: i: In each loop iteration, segment specifies which segment of the scan operation this
specific request is handling. The loop runs for each segment.
3. [Link](promises): Runs all the scan promises in parallel and waits for them to finish.
4. Combining Results: Once all scans are complete, the results are combined into a single array.
Considerations:
• Number of Segments: The number of parallel segments should be chosen based on the size of your
table and the available read capacity. More segments will make the scan faster but will use more read
capacity.
• Scan Costs: Scans can be expensive in DynamoDB, especially with large datasets. Consider using a
query when possible, as queries are much more efficient.
try {
// Wait for all the scans to complete
const results = await [Link](promises);
// Combine all results
const allResults = [Link](); // Flatten the array of arrays
[Link]('All scanned items:', allResults);
} catch (error) {
[Link]('Error during parallel scan:', error);
}
};
Conclusion:
In Dynamoose, you can perform a parallel scan by dividing the scan into multiple segments using the parallel
option. This improves the performance of scanning large tables in DynamoDB. The above example demonstrates how
to use the parallel scan feature efficiently by distributing the work across multiple segments and combining the
results once all scans are complete.
print(typeof(NaN));
NaN in Javascript is defined to be of type number despite its name(not a number).
Q 72. What is the output?
Ans.
var a = [Link]();
var b = [Link]();
print(a);
print(b);
The output of the code will be:
-Infinity
Infinity
Here's why:
1. [Link]() without arguments: When called without any arguments, [Link]()
returns -Infinity. This is because it's looking for the largest number among an empty
set, and by convention, the largest number in an empty set is considered to be -
Infinity.
2. [Link]() without arguments: Similarly, when called without any arguments,
[Link]() returns Infinity. This is because it's looking for the smallest number
among an empty set, and the smallest number in an empty set is considered to be
Infinity.
Q 73. What will be the output of the following code snippet?
(function(){
setTimeout(()=> [Link](1),2000);
[Link](2);
setTimeout(()=> [Link](3),0);
[Link](4);
})();
First the 2 is printed with the [Link], then even with a time delay of 0ms, the 4 is
printed before the 3 because JS executes setTimeout with the Web API, and so the entire
function is executed first. Lastly, after a delay of 2000ms, the 1 is printed.
Q 74. When an operator’s value is NULL, the typeof returned by the unary operator is:
Ans. Any NULL value of operator will always return typeof object.
Q 75. When the switch statement matches the expression with
the given labels, how is the comparison done?
Ans. Switch performs an ‘===’ based comparison, i.e both the value of the expression
and its datatype is compared.
• These files are also transpiled from JSX/ES6+ syntax to browser-compatible ES5 code using Babel.
• Minified code looks smaller and less readable, making it more efficient for production environments.
• If the app’s source code remains the same, the cached files can be reused, improving page load speed
for returning users.
• It contains a reference to the bundled JavaScript and CSS files, and any other static assets needed for
the app to run.
• Dead code elimination further removes any code that isn’t needed at runtime.
• By default, React’s build process creates source maps, but you can configure this behavior.
Output Example:
Once the npm run build command completes, the build folder typically contains:
/build
/static
/css
[Link]
/js
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
Conclusion:
npm run build prepares your React app for production by bundling, minifying, and optimizing the code, making
it smaller and faster. The result is a set of static files that can be deployed to a web server or a hosting platform, such
as Netlify, Vercel, or AWS S3. This process ensures the app runs efficiently in a production environment.
Q 78. What are the next steps to deploy the above build via s3 and cloudfront?
Ans. Deploying a React app via Amazon S3 and CloudFront is a great way to serve static files efficiently. Here's a
step-by-step guide to deploying your React app:
a. Login to AWS:
• Go to the AWS Management Console and log in.
• Give your bucket a unique name (e.g., my-react-app-bucket) and select the region closest to your
target audience.
• Uncheck "Block all public access" (since your static files need to be publicly accessible). Confirm this by
acknowledging the warning.
– Under Properties, find the Static website hosting option and enable it.
– Set the index document to [Link] (React apps usually have [Link] as their entry
point).
– You can also set a custom error document like [Link], but typically React handles routing
internally.
json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::your-bucket-name/*"
}
]
}
– Ensure the files are public (based on your bucket policy) so they can be accessed by the web.
a. Navigate to CloudFront:
• In the AWS console, go to CloudFront.
• Set the origin access control (OAC) to allow CloudFront to read from your bucket. This enhances
security as users only access content through CloudFront and not directly from S3.
– Set the Viewer Protocol Policy to Redirect HTTP to HTTPS for better security.
• Set HTTP Error Code to 404 and set Customize Error Response to "Yes".
a. Invalidate Cache:
• Go to your CloudFront Distribution in the AWS console.
• Create a new invalidation and set the path to /* to invalidate all the cached files.
c. Set Up SSL:
• Request a SSL certificate from AWS Certificate Manager (ACM).
• Once validated, configure the CloudFront distribution to use this SSL certificate.
• Make sure everything works, especially routes (with React Router) and that all assets are loading
correctly.
Summary of Steps:
1. Create an S3 bucket, enable static website hosting, and upload your build folder.
Streams in [Link] can be thought of as a continuous flow of data that can be processed piece by piece.
2. Writable Streams: These streams allow you to write data chunk by chunk. Examples include writing to
a file, HTTP responses, or writing to a network socket.
3. Duplex Streams: These streams are both readable and writable. Examples include TCP sockets.
4. Transform Streams: These streams are a special case of Duplex streams where the output is
computed based on the input. An example is the zlib stream for compression.
• Performance: Processing data in smaller chunks improves performance and responsiveness, especially
when dealing with large files or real-time data.
// Listen for the 'end' event to know when the file is fully read
[Link]('end', () => {
[Link]('File reading finished');
});
// Handle errors
[Link]('error', (err) => {
[Link]('Error reading file:', err);
});
In the above example, the file is read in chunks, and each chunk is processed as soon as it becomes available. This
approach is more memory-efficient than reading the entire file at once.
3. Pipe Between Streams (Using a readable stream and piping it into a writable
stream)
One common use of streams is to pipe a readable stream directly into a writable stream. For instance, copying a file
without manually handling the chunks:
javascript
const fs = require('fs');
// Handle errors
[Link]('error', (err) => [Link]('Read error:', err));
[Link]('error', (err) => [Link]('Write error:', err));
In this example, the pipe method automatically reads from the readableStream and writes to the
writableStream without manually managing the chunks. This is a common pattern for streaming operations in
[Link].
Conclusion:
Streams in [Link] provide an efficient way to process data, especially large amounts of it, by handling it in chunks.
Whether you're working with files, network data, or real-time communication, streams help to minimize memory
usage and improve performance.
• Writable Streams: For writing data (e.g., file writes, HTTP responses).
• Duplex Streams: For both reading and writing (e.g., TCP sockets).
• <article>: Represents an independent piece of content (like a blog post, news article, etc.).
• <section>: Defines sections in a document, such as chapters, headers, or any thematic grouping of
content.
• <aside>: Represents content that is related to the surrounding content but somewhat separate from
the main flow, like sidebars or callouts.
• <figure> and <figcaption>: Used to encapsulate media like images, videos, charts, and the
associated captions.
1. Semantic tags make it easier for assistive technologies like screen readers to understand the
structure of a webpage. For example, screen readers can easily identify headings, navigation
menus, and footers, allowing users with disabilities to navigate content more efficiently.
1. Search engines like Google use semantic tags to better understand the content on the page.
For example, content inside an <article> or <section> tag may be treated differently
from generic content inside a <div> tag. This can improve how search engines index and rank
a webpage.
1. Semantic tags make the HTML structure more readable and easier for developers to
understand. A well-structured document helps developers (or future maintainers) to quickly
identify sections of the page, leading to better collaboration and code maintenance.
4. Improved Consistency:
1. Semantic tags help developers create a consistent structure across a website. Instead of using
non-semantic tags (like <div>) with a class or ID for every type of section, developers can use
semantic elements (like <header>, <footer>, etc.), leading to more uniform and predictable
structures.
1. Browsers are designed to recognize and handle semantic tags properly, which improves the
rendering of content. Semantic tags also help browsers identify different sections of a
webpage (like headers, footers, navigation bars) and style them more appropriately.
6. Future-Proofing:
1. As HTML evolves, semantic tags are more likely to be supported in future web standards. By
using them, developers ensure that their code remains compliant with modern best practices,
making it easier to update or refactor in the future.
html
<div id="header">Welcome to My Website</div>
<div id="nav">Home | About | Contact</div>
<div id="main-content">This is the main content of the page.</div>
<div id="footer">Copyright 2023</div>
• Semantic tags:
html
<header>Welcome to My Website</header>
<nav>Home | About | Contact</nav>
<main>This is the main content of the page.</main>
<footer>Copyright 2023</footer>
In the second example, it is clearer what each section of the page is for, just by looking at the tag names.
Conclusion:
Semantic tags enhance both the user experience and the development process. They improve the accessibility, SEO,
and structure of web pages while making the code easier to understand, maintain, and future-proof. By using
semantic tags, developers can create websites that are more robust, user-friendly, and optimized for search engines.
1. Webpack is a bundler that manually compiles and bundles JavaScript (and other files) into a final
output. It allows custom configurations for optimization, file splitting, and more. You control the build
process by setting up loaders and plugins.
2. npm start in React (via Create React App) uses a preconfigured Webpack under the hood,
abstracting away the setup. It automatically handles development tasks like live reloading, fast builds,
etc.
For custom setups, Webpack offers more flexibility.
• <meta name="description">: Provides a brief summary of the page's content. Search engines
use this to display a short snippet of the page's content in search results.
• <meta name="keywords">: Specifies keywords related to the page's content. While less commonly
used by search engines nowadays, they can still be helpful for SEO.
• <meta name="viewport">: Defines the viewport settings for mobile devices, controlling the page's
scaling and layout. This is crucial for ensuring proper rendering on different screen sizes.
• <meta name="robots">: Provides instructions to search engine robots about how to index and
follow the page. For example, you can use noindex to prevent the page from appearing in search
results.
• <meta name="og:title">: Specifies the title of the page that will be displayed on social media
platforms.
• <meta name="og:description">: Specifies the description of the page that will be displayed on
social media platforms.
• <meta name="og:image">: Specifies the URL of the image that will be used as the thumbnail on
social media platforms.
Example:
html
<!DOCTYPE html>
<html>
<head>
<title>My Website</title>
<meta charset="UTF-8">
<meta name="description" content="This is a sample website with meta
tags.">
<meta name="keywords" content="HTML, CSS, JavaScript, web development">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="author" content="John Doe">
</head>
<body>
</body>
</html>
In this example, the meta tags provide information about the website's title, description, keywords, viewport
settings, and author. This information can be used by search engines, social media platforms, and other applications
to understand the page's content and display it appropriately.