Interview Questions
React
React
What are the features of React?
- Uses a virtual DOM instead of manipulating the real DOM directly.
- Supports server-side rendering (SSR) with hydration.
- Follows unidirectional data flow.
- Encourages reusable, composable UI components.
What do you know about the Virtual DOM?
- The Virtual DOM (VDOM) is an in-memory representation of the real DOM.
- It starts as a copy of the real DOM and updates are computed against it.
Update steps:
- When data changes, React re-renders the UI into the Virtual DOM.
- React diffs the previous and current Virtual DOM trees.
- React applies minimal changes to the real DOM.
Differentiate between Real DOM and Virtual DOM
What do you understand from “In React, everything is a component.”
- Components are the building blocks of a React UI.
- They split the UI into small, independent, reusable pieces.
- Each component renders independently without affecting other parts of the UI.
Explain the purpose of render() in React.
- Class components implement
render()to return a React element. - The returned element describes what should appear in the DOM.
How can you embed two or more components into one?
class MyComponent extends React.Component {
render() {
return (
<div>
<h1>Hello</h1>
<Header />
</div>
);
}
}
class Header extends React.Component {
render() {
return <h1>Header Component</h1>;
}
}
ReactDOM.render(<MyComponent />, document.getElementById('content'));What are Props?
Props are short hand for Properties in React. They are read-only components which must be kept pure i.e. immutable. They are always passed down from the parent to the child components throughout the application. A child component can never send a prop back to the parent component. This help in maintaining the unidirectional data flow and are generally used to render the dynamically generated data.
What is a state in React and how is it used?
- State is a component-owned object that holds information that changes over time.
- Unlike props, state is private, mutable, and controlled by the component.
What are the different phases of React component’s lifecycle?
- Mounting:
constructor,getDerivedStateFromProps,render,componentDidMount. - Updating:
getDerivedStateFromProps,shouldComponentUpdate,render,getSnapshotBeforeUpdate,componentDidUpdate. - Unmounting:
componentWillUnmount.
Explain the lifecycle method componentWillMount()
Executed just before rendering takes place both on the client as well as server-side.
Explain the lifecycle method componentDidMount()
Executed on the client side only after the first render.
Explain the lifecycle method componentWillReceiveProps()
Invoked as soon as the props are received from the parent class and before another render is called.
Explain the lifecycle method shouldComponentUpdate()
Returns true or false value based on certain conditions. If you want your component to update, return true else return false. By default, it returns true.
Explain the lifecycle method componentWillUpdate()
Called just before rendering takes place in the DOM.
Explain the lifecycle method componentDidUpdate()
Called immediately after rendering takes place.
Explain the lifecycle method componentWillUnmount()
Called after the component is unmounted from the DOM. It is used to clear up the memory spaces.
What is a synthetic event?
Synthetic events are the objects which act as a cross-browser wrapper around the browser’s native event. They combine the behavior of different browsers into one API. This is done to make sure that the events show consistent properties across different browsers. examples: onClick, onBlur, etc.
What are Higher Order Components(HOC)?
- A HOC is a component that wraps another component to reuse logic.
- It’s a pattern leveraging React’s compositional nature.
- HOCs don’t modify the input component’s behavior; they compose it.
- Benefits include:
- Code reuse and logic abstraction
- Render hijacking
- State abstraction/manipulation
- Props manipulation
In which lifecycle event do you make AJAX requests and why?
- Perform data fetching in
componentDidMount(oruseEffectin function components). - Ensures the component is mounted before calling
setState. - Avoids updates on unmounted components.
How do you tell React to build in Production mode and what will that do?
- Configure your bundler to set
process.env.NODE_ENV = 'production'. - Enables production optimizations and removes development warnings.
- Minify code to leverage dead-code elimination and reduce bundle size.
What is JSX (JS XML)?
- JSX is syntax sugar for
React.createElement(). - It lets you write component templates in HTML-like syntax that compile to JavaScript.
What is React?
React is an open-source front-end JavaScript library that is used for building user interfaces, especially for single-page applications. It is used for handling view layer for web and mobile apps.
What is the difference between state and props?
- Props are inputs passed to a component (like function parameters).
- State is managed within the component (like local variables) and can change over time.
"What is ""key"" prop?"
keyis a special string attribute used in lists to help React identify items.- Improves diffing by tracking inserted, removed, or changed elements.
What is context?
- Context lets you pass data through the component tree without prop drilling.
What is reconciliation?
<!-- id: Ll)X1;&(😗, noteType: Basic-66869 -->
- When props/state change, React compares the new element with the previous.
- If different, React updates the DOM minimally — this is reconciliation.
What are fragments?
- Fragments let components return multiple children without extra DOM nodes.
- Use
<>...</>or<React.Fragment>...</React.Fragment>.
What are error boundaries in React v16?
- Error boundaries catch errors in child components and render fallback UI.
- Implement with
componentDidCatch(error, info)and/orstatic getDerivedStateFromError().
What is the use of react-dom package?
- Provides DOM-specific methods for React apps:
render(element, container)hydrate(element, container)(for SSR hydration)unmountComponentAtNode(container)findDOMNode(instance)(prefer refs instead)createPortal(child, container)
What is ReactDOMServer?
- Enables rendering components to static markup for SSR.
- Common methods:
renderToString(component)renderToStaticMarkup(component)
Example:
import ReactDOMServer from 'react-dom/server';
const html = ReactDOMServer.renderToString(<App />);
// send html as responseWhy is a component constructor called only once?
React's reconciliation algorithm assumes that if a custom component appears in the same place on subsequent renders, it's the same component as before, so reuses the previous instance rather than creating a new one.
What are the common folder structures for React?
- Grouping by feature or route (co-locate components, hooks, tests).
- Grouping by file type (components, hooks, styles, tests in separate dirs).
What is the benefit of styles modules?
It is recommended to avoid hard coding style values in components. Any values that are likely to be used across different UI components should be extracted into their own modules.
What is React Router?
- A routing library that keeps the UI in sync with the URL.
- Hooks:
useNavigate(v6),useLocation,useParams. - Covers:
- Configuring routes
- Navigating with
Link - Nested routes/layouts
- Programmatic navigation
- URL params and search params
How React Router is different from history library?
- React Router wraps the
historylibrary, managing browser and hash histories. - Adds declarative routing components and React integration.
- Provides memory history for non-browser environments (React Native, tests).
What is React Interalization?
is part of FormatJS which provides bindings to React. It helps to format strings, dates, numbers, or pluralization
What is Flux?
- Flux is an architectural pattern favoring unidirectional data flow over MVC.
- Complements React; used internally at Facebook.
What is Redux?
- Redux is a predictable state container inspired by Flux.
- Works with React or other view libraries.
- Hooks:
useSelector,useDispatch.
What are the core principles of Redux?
- Single source of truth: entire app state in one store.
- State is read-only: only actions describe state changes.
- Changes via pure functions: reducers transform state based on actions.
What is the difference between mapStateToProps() and mapDispatchToProps()?
mapStateToProps() is a utility which helps your component get updated state (which is updated by some other components) mapDispatchToProps() is a utility which will help your component to fire an action event (dispatching action which may cause change of application state)
Can I dispatch an action in reducer?
Your reducer should simply digest the action payload and returning a new state object. Adding listeners and dispatching actions within the reducer can lead to chained actions and other side effects.
What is the difference between React context and React Redux?
Context is built in tool with React and required minimal setup, whereas Redux requires additional installation and extensive setup to integrate it with a React Application. Context is specifically designed for static data, that is not often refreshed or updated, whereas Redux is better in the high-frequency update data field. Context used for UI logic and State Management Logic are in the same component, whereas Redux has better code organization with separate UI logic and State Management Logic Redux ease to debug with Redux Dev Tool
How to make AJAX request in Redux?
You can use redux-thunk middleware which allows you to define async actions.
What is the difference between component and container in React Redux?
Component is a class or function component that describes the presentational part of your application. Container is an informal term for a component that is connected to a Redux store. Containers subscribe to Redux state updates and dispatch actions, and they usually don't render DOM elements; they delegate rendering to presentational child components.
What is redux-saga and its benifits?
redux-saga is a library that aims to make side effects (asynchronous things like data fetching and impure things like accessing the browser cache) in React/Redux applications easier and better. Benifits: - make asynchronous flows easy to read, write, and test - enable numerous approaches to tackling parallel execution, task concurrency, task racing, task cancellation, and more
What are the differences between call() and put() in redux-saga?
Both call() and put() are effect creator functions. call() function is used to create effect description, which instructs middleware to call the promise. put() function creates an effect, which instructs middleware to dispatch an action to the store.
What is Redux Thunk?
Redux Thunk middleware allows you to write action creators that return a function instead of an action. The thunk can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met. The inner function receives the store methods dispatch() and getState() as parameters.
What are the differences between redux-saga and redux-thunk?
Both Redux Thunk and Redux Saga take care of dealing with side effects. In most of the scenarios, Thunk uses Promises to deal with them, whereas Saga uses Generators. Thunk is simple to use and Promises are familiar to many developers, Sagas/Generators are more powerful but you will need to learn them. But both middleware can coexist, so you can start with Thunks and introduce Sagas when/if you need them.
What are Redux selectors and why to use them?
- Selectors take state and return derived data for components.
- Benefits:
- Compute derived data to keep state minimal.
- Memoize to avoid recomputation unless inputs change.
What is an action in Redux?
Actions are plain JavaScript objects or payloads of information that send data from your application to your store. Actions must have a type property that indicates the type of action being performed.
What is reselect and how it works?
Reselect is a selector library (for Redux) which uses same concept with Redux Selector. It was originally written to compute derived data from Redux-like applications state, and not recomputed unless one of it arguments changed. It supports to create a new selector which receive other selectors as argument.
What are Styled Components?
styled-componentslets you style components using CSS-in-JS.- Co-locates styles with components and removes CSS-to-component mapping.
Do I need to keep all my state into Redux? Should I ever use react internal state?
It is up to the developer's decision. There are the some rules to determine what kind of data should be put into Redux Is the same data existed in store?Do other parts of the application care about this data?Do you need to be able to create further derived data based on this original data?
What is the purpose of registerServiceWorker in React?
React creates a service worker for you without any configuration by default. The service worker is a web API that helps you cache your assets and other files so that when the user is offline or on a slow network, he/she can still see results on the screen, as such, it helps you build a better user experience. It's all about adding offline capabilities to your site.
What is React memo function?
Class components can be restricted from re-rendering when their input props are the same using PureComponent or shouldComponentUpdate. Now you can do the same with function components by wrapping them in React.memo.
What is React lazy function?
The React.lazy function lets you render a dynamic import as a regular component. It will automatically load the seperated bundle containing the imported component when the component gets rendered. The module must be a default export containing a React component.
What are hooks? What rules need to be followed for hooks?
Hooks is a new feature(React 16.8) that lets you use state and other React features without writing a class. You need to follow two rules in order to use hooks,Call Hooks only at the top level of your react functions. i.e, You shouldn’t call Hooks inside loops, conditions, or nested functions.Call Hooks from React Functions or another hooks only.The naming convention of hooks should start with the prefix use
In which scenarios error boundaries do not catch errors?
Below are the cases in which error boundaries doesn't work:Inside Event handlers Asynchronous code using setTimeout or requestAnimationFrame callbacks During Server side rendering When errors thrown in the error boundary code itself
What is the proper placement for error boundaries?
- You can wrap top-level route components to display a generic error message for the entire application. - You can also wrap individual components in an error boundary to protect them from crashing the rest of the application and create the error state for each of components independently
What is the methods order when component re-rendered?
An update can be caused by changes to props or state. The below methods are called in the following order when a component is being re-rendered.static getDerivedStateFromProps()shouldComponentUpdate()render()getSnapshotBeforeUpdate()componentDidUpdate()
What are the methods invoked during error handling?
Below methods are called when there is an error during rendering, in a lifecycle method, or in the constructor of any child component.static getDerivedStateFromError()componentDidCatch()
What is the purpose of unmountComponentAtNode method?
This method is available from react-dom package and it removes a mounted React component from the DOM and clean up its event handlers and state. If no component was mounted in the container, calling this function does nothing. Returns true if a component was unmounted and false if there was no component to unmount.
What is NextJS and major features of it?
Next.js is a popular and lightweight framework for static and server‑rendered applications built with React. It also provides styling and routing solutions. Below are the major features provided by NextJS,Server-rendered by defaultAutomatic code splitting for faster page loadsSimple client-side routing (page based)Webpack-based dev environment which supports (HMR)Able to implement with Express or any other Node.js HTTP serverCustomizable with your own Babel and Webpack configurations
Optimizing performance in a React application? List the React hook functions
Keeping component state local where necessary. (useState, useEffect)Split component to small ones if it becomes more complex.Avoid pass props down in many levels (State management: React-redux, useContext, useReducer)Memoizing React components to prevent unnecessary re-renders. (React.memo)Memoizing expensive React states or methods to reduce recomputation. (useMemo, useCallback)Building a custom hook to extract a logic into a reusable function Use refs to store mutable values without re-rendering the entire component.use debounce & throttle to avoid send multiple requests in a short time. Code-splitting in React using dynamic import()Windowing or list virtualizationLazy loading images
React vs Angular
React is a library, but Angular is a Full-featured Framework. The virtual DOM and one-way data binding are used by React.js, but the real DOM and two-way data binding are used by Angular.
How to write unit tests for custom hooks?
We would use react-hooks-testing-library write the unit test. There are two methods we need to know: renderHook: The renderHook can render custom hook, you can operations the custom hook like in the component.act: The act can execute the methods return from custom hook that makes sure all updates have been processed Reference: React | Write a unit test for custom hooks in ten minutes - DEV Community
What is React Testing Library?
React Testing Library is a set of helpers builds on top of DOM Testing Library that let you test React components. This allows you to get your tests closer to using your components the way a user will It's supported by CRA as default. Sample test steps: - Arrange (render): The method renders a React element into the DOM. - Act (fireEvent): The method allows you to fire events to simulate user actions. - Assert: assert that the test case is correct
Testing Recipes in React components
Setup/Teardown (Arrange): setup a DOM element as a render target (beforeEach) or “clean up” and unmount the tree on exiting (afterEach) act / assert: makes sure all updates related to these “units” have been processed and applied to the DOM before you make any assertions Rendering: test whether a component renders correctly for given props. Data Fetching: mock requests with dummy data Mocking Modules: Mocking out modules (ex: 3rd libraries) with dummy replacements Events: dispatching real DOM events on DOM elements Timers: You can use fake timers only in some tests Snapshot Testing: you save “snapshots” of the rendered component output ensure that a change is correct
What are end-to-end tests?
End-to-end tests are useful for testing longer workflows, especially when they’re critical to your business (such as payments or signups). For these tests, you’d probably want to test how a real browser renders the whole app, fetches data from the real API endpoints, uses sessions and cookies, navigates between different links. We can assert on side effects not just in the browser, but potentially on the backend as well.
Recoil State management core concepts
Recoil is a state management library for React. Recoil lets you create a data-flow graph that flows from atoms (shared state) through selectors (pure functions) and down into your React components. Atoms are units of state that components can subscribe to. When an atom is updated, each subscribed component is re-rendered with the new value. Atoms can be used in place of React local component state. If the same atom is used from multiple components, all those components share their state. Selectors is a pure function that accepts atoms or other selectors as input. When these upstream atoms or selectors are updated, the selector function will be re-evaluated. Components can subscribe to selectors just like atoms, and will then be re-rendered when the selectors change. Popular components: - RecoilRoot: Components that use recoil state need RecoilRoot to appear somewhere in the parent tree. A good place to put this is in your root component - Atom: An atom represents a piece of state. Atoms can be read from and written to from any component. Components that read the value of an atom are implicitly subscribed to that atom, so any atom updates will result in a re-render of all components subscribed to that atom - Selector: A selector represents a piece of derived state. Derived state is a transformation of state. You can think of derived state as the output of passing state to a pure function that modifies the given state in some way - Components that need to read from and write to an atom should use useRecoilState() - We can use the useRecoilValue() hook to read the value of selector Getting Started | Recoil (recoiljs.org)
Client Site Rendering (CSR), Server Site Rendering (SSR) and SSG (Static Site Generation)
- CSR: Server sending HTML and JS files -> Browser downloads JS -> Browser executes React -> Page full dynamic (loaded) - SSR: Server built out HTML page and sends to the browser -> Static HTML is rendered and Browser downloads JS in background (loaded) -> Loaded React adds interactivity to the page -> Page full dynamic - SSG: HTML files are generated on build time -> Static HTML is rendered and Browser downloads JS in background-> Loaded React adds interactivity to the page -> Page full dynamic Usage: - CSR: Login page, dashboard page, ... and the pages don't need SEO - SSR: page with dynamic data but still have SEO and expect super fast initial loading - SSG: for pages which don't need to be updated frequently and expect super fast initial loading
How to Create a React Component Library
InitCreating ComponentsAdding TypescriptAdding RollupBuilding Your LibraryMore advances: Adding CSSOptimizingAdding TestsAdding StorybookAdding SCSS
When should you memoize in React?
When should you memoize in React (prateeksurana.me)
What is React Fiber?
Fiber is the new reconciliation engine in React 16. Its main goal is to enable incremental rendering of the virtual DOM. Fiber improves the Virtual DOM and comparation steps of reconcilation algo
useState hook
- Returns a stateful value, and a function to update it. - During the initial render, the returned state (state) is the same as the value passed as the first argument (initialState). - Lazy initial state: The initialState argument is the state used during the initial render. In subsequent renders, it is disregarded. If the initial state is the result of an expensive computation, you may provide a function instead, which will be executed only on the initial render - The setState function is used to update the state. It accepts a new state value and enqueues a re-render of the component. - If the new state is computed using the previous state, you can pass a function to setState. The function will receive the previous value, and return an updated value. - During subsequent re-renders, the first value returned by useState will always be the most recent state after applying updates. - React guarantees that setState function identity is stable and won’t change on re-renders. This is why it’s safe to omit from the useEffect or useCallback dependency list. - Bailing out of a state update: If you update a State Hook to the same value as the current state, React will bail out without rendering the children or firing effects (React uses the Object.is comparison algorithm.) - Batching of state updates: React may group several state updates into a single re-render to improve performance.
useRef
useRef returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). The returned object will persist for the full lifetime of the component. The only difference between useRef() and creating a {current: ...} object yourself is that useRef will give you the same ref object on every render. Keep in mind that useRef doesn’t notify you when its content changes. Mutating the .current property doesn’t cause a re-render
React Profiler API
The Profiler measures how often a React application renders and what the “cost” of rendering is. Its purpose is to help identify parts of an application that are slow and may benefit from optimizations such as memoization.
When exactly does React clean up an effect?
React performs the cleanup when the component unmounts. However, effects run for every render and not just once. This is why React also cleans up effects from the previous render before running the effects next time.
useEffect
- By default, effects run after every completed render - Allow us Cleaning up an effect before the component is removed from the UI - if a component renders multiple times (as they typically do), the previous effect is cleaned up before executing the next effect - Timing: useEffect is deferred until after the browser has painted (rendered) - Conditionally firing an effect + only be recreated when deps changes + If you pass an empty deps array, only be created after the intial rendered Practice challenge: https://www.greatfrontend.com/questions/javascript/use-query?framework=react&tab=coding https://react.dev/learn/synchronizing-with-effects
useEffect vs useLayoutEffect
useEffect runs asynchronously after the browser paints, making it ideal for side effects that don't affect layout. useLayoutEffect runs synchronously before painting, perfect for DOM measurements or preventing visual flicker, but should be used sparingly as it blocks the browser's painting process
NextJS + Astro
NextJS to Astro: more control = faster sites - YouTube
useEffect called twice in react 18
amazing features that Identifying unsafe lifecycles => we shouldn't disable it
JavaScript
JavaScript
What is the Document Object Model (DOM)?
The Document Object Model (DOM) is a programming interface for web documents. It represents the structure of a document as a tree of objects, where each object corresponds to a part of the document (e.g., elements, attributes, text). The DOM allows developers to access and manipulate the content, structure, and style of a web page using JavaScript.
How do you add an event listener to an element?
To add an event listener on an element, first get that element through one of the document methods (e.g. getElementById). Then use the element’s addEventListener method.
The method receives the event name (e.g. click, keyup, mouseup), the event handler function, and optionally options such as capture.
const button = document.getElementById('submit');
function handleClick(e) { console.log('Clicked!', e.target); }
button.addEventListener('click', handleClick, { capture: false });What is the difference between null and undefined?
In JavaScript, “undefined” is the default value new variables take, and it means the variable has been defined but it hasn’t been assigned any value just yet.
And “null” is actually a value that signals “no value” or “no object”, it is specifically assigned to the variable by the developer.
What is the difference between cookies, sessionStorage, and localStorage?
Cookies are small pieces of data that are stored on the client-side (i.e. in the user's browser). They are sent back to the server with every HTTP request, which allows servers to identify and remember information about the user. Cookies are commonly used for things like session management, user authentication, and personalization.
SessionStorage and localStorage are two mechanisms for storing data on the client-side, but they differ in how they persist data. sessionStorage stores data for the duration of the page session, which means that the data is lost when the user closes the browser tab or window. localStorage, on the other hand, stores data indefinitely, even after the browser is closed.
Use case:
- Cookies: Used for session management, user authentication, and personalization.
- sessionStorage: Used for storing temporary data that should be available for the duration of the page session.
- localStorage: Used for storing data that should persist even after the browser is closed.
How does the browser render a website?
What are closures, and how/why would you use them?
A closure is a function that has access to the variables in its outer scope, even after the outer function has returned. In other words, a closure allows a function to “remember” the environment in which it was created.
Closures are commonly used in JavaScript for things like creating private variables and functions, implementing currying, and avoiding memory leaks.
Explain why the following doesn't work as an IIFE: function foo(){ }();. What needs to be changed to properly make it an IIFE?
IIFE (Immediately Invoked Function Expression)
Definition
- An IIFE is a function expression that runs immediately after it is created. It creates a private scope and avoids polluting the global scope.
Why function foo(){}(); throws
function foo(){}is parsed as a function declaration.- The trailing
();tries to call a function but there is no expression to call, resulting inUncaught SyntaxError: Unexpected token ).
Correct syntax
(function foo() {
// code
})();
// or
(function foo() {
// code
})();
// or using arrow functions
(() => {
// code
})();Why parentheses matter
- Wrapping the function in
()turns the declaration into a function expression, which can then be immediately invoked with the trailing(). - The function does not leak into the global scope; you may omit the name unless self-reference is needed.
Using void (and its caveat)
const result = void (function bar() {
return 'foo';
})();
console.log(result); // undefinedvoidforces the expression to evaluate toundefined, so you cannot use the function’s return value. Prefer the parentheses form if you need the returned value.
Typical use cases
- Create a one-off initialization.
- Encapsulate variables and avoid globals.
- Implement module patterns or set up event listeners with private state.
Explain how this works in JavaScript
The value of this depends on how the function is called.
Rules:
- Called with
new:thisis a brand new object. - Called via
apply,call, orbind:thisis the object passed as the first argument. - Called as a method (e.g.,
obj.method()):thisis the object owning the method. - Called as a plain function:
thisis the global object (windowin browsers). In strict mode,thisisundefined. - If multiple rules apply, precedence determines
this. - Arrow functions ignore all above and capture
thisfrom the enclosing lexical scope at creation.
ES6 changes:
- Arrow functions use enclosing lexical
this. This is convenient but prevents callers from controlling context via.callor.apply. - Be mindful when refactoring legacy code relying on dynamic
thisbinding.
References:
- https://codeburst.io/the-simple-rules-to-this-in-javascript-35d97f31bde3
- https://stackoverflow.com/a/3127440/1751946
Explain how prototypal inheritance works
All JavaScript objects have a prototype property that references another object. When a property is accessed on an object and is not found, the engine looks up the prototype chain until it finds the property or reaches the end. This behavior simulates classical inheritance but is more accurately delegation.
Example: polyfill for Object.create
if (typeof Object.create !== 'function') {
Object.create = function (parent) {
function Tmp() {}
Tmp.prototype = parent;
return new Tmp();
};
}Example: inheritance via prototypes
function Parent() { this.name = 'Parent'; }
Parent.prototype.greet = function () { console.log('hello from Parent'); };
const child = Object.create(Parent.prototype);
child.cry = function () { console.log('waaaaaahhhh!'); };
child.cry(); // waaaaaahhhh!
child.greet(); // hello from ParentNotes:
.greetis not defined onchild, so the engine goes up the prototype chain and finds it onParent.prototype.- Use
Object.create(Parent.prototype)for prototype methods to be inherited. child.constructorpoints toParentby default.
Correcting constructor with a subtype
function Child() { Parent.call(this); this.name = 'child'; }
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
const c = new Child();
c.cry = function () { console.log('waaaaaahhhh!'); };
c.cry(); // waaaaaahhhh!
c.greet(); // hello from Parent
console.log(c.constructor.name); // 'Child'References:
- https://www.quora.com/What-is-prototypal-inheritance/answer/Kyle-Simpson
- https://davidwalsh.name/javascript-objects
- https://crockford.com/javascript/prototypal.html
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain
What's the difference between a variable that is: null, undefined or undeclared? How would you go about checking for any of these states?
Undeclared
- Created when assigning to an identifier not previously declared with
var,let, orconst. - Defined globally (outside current scope). In strict mode, a
ReferenceErroris thrown on assignment. - Avoid at all costs. To detect, wrap usage in
try/catch.
function foo() { x = 1; } // ReferenceError in strict mode
try { foo(); } catch (e) { console.error(e); }Undefined
- Declared but not assigned a value; type is
undefined. - Functions without a return value evaluate to
undefined. - Check using strict equality or
typeof. Do not use==which also matchesnull.
var foo;
console.log(foo); // undefined
console.log(foo === undefined); // true
console.log(typeof foo === 'undefined'); // true
console.log(foo == null); // true (wrong check)
function bar() {}
var baz = bar();
console.log(baz); // undefinedNull
- Explicitly assigned
nullrepresents no value; different fromundefined. - Check using strict equality; avoid
==which matchesundefined.
var foo = null;
console.log(foo === null); // true
console.log(typeof foo === 'object'); // true
console.log(foo == undefined); // true (wrong check)Personal habit: explicitly assign null if a variable is declared but not yet used. Linters will help catch references to undeclared variables.
References:
- https://stackoverflow.com/questions/15985875/effect-of-declared-and-undeclared-variables
- https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/undefined
What is a closure, and how/why would you use one?
A closure gives you access to an outer function's scope from an inner function. It combines a function and the lexical environment in which it was declared.
Closure scope chains:
- Own scope (variables defined within the function).
- Outer function variables.
- Global variables.
Why use closures?
- Data privacy / emulate private methods (module pattern).
- Partial application or currying.
Reference: Closures - JavaScript | MDN (mozilla.org).
Can you describe the main difference between a .forEach loop and a .map() loop and why you would pick one versus the other?
To understand the differences, consider what each function does.
.forEach
- Iterates through array elements.
- Executes a callback for each element.
- Does not return a value.
const a = [1, 2, 3];
const doubled = a.forEach((num, index) => {
// Do something with num and/or index
});
console.log(doubled); // undefined.map
- Iterates through array elements.
- Maps each element to a new element by calling a function on each element, creating a new array.
const a = [1, 2, 3];
const doubled = a.map(num => num * 2);
console.log(doubled); // [2, 4, 6]Main difference:
.map()returns a new array. If you need the result and do not wish to mutate the original array,.map()is the clear choice.- If you simply need to iterate over an array,
.forEachis fine.
What's the difference between host objects and native objects?
Native objects are part of the JavaScript language defined by the ECMAScript specification (e.g., String, Math, RegExp, Object, Function). Host objects are provided by the runtime environment (browser or Node), such as window, XMLHttpRequest, etc.
What's the difference between .bind, .call and .apply?
call and apply invoke a function immediately and set this.
call(thisArg, a, b)— comma-separated arguments.apply(thisArg, [a, b])— arguments as an array.bindreturns a new function withthis(and optionally leading args) fixed.
function add(a, b) { return a + b; }
console.log(add.call(null, 1, 2)); // 3
console.log(add.apply(null, [1, 2])); // 3
function Temp() { this.c = 1; }
Temp.prototype.add = function (a, b) { return (this.c || 0) + a + b; };
const temp = new Temp();
console.log(temp.add(1, 2)); // 4
console.log(temp.add.call({ c: 2 }, 1, 2)); // 5
console.log(temp.add.apply({ c: 3 }, [1, 2])); // 6
const bound = temp.add.bind({ c: 4 });
console.log(bound(1, 2)); // 7Explain Function.prototype.bind.
Definition
bind(thisArg, ...args)returns a new function withthisfixed tothisArgand optionally prependsargs.
Why use it
- Preserve method
thiswhen passing as a callback. - Partially apply leading arguments.
Example
const module = {
x: 42,
getX() { return this.x; }
};
const unbound = module.getX;
console.log(unbound()); // undefined in strict mode
const bound = module.getX.bind(module);
console.log(bound()); // 42
function add(a, b, c) { return a + b + c; }
const add5 = add.bind(null, 5);
console.log(add5(1, 2)); // 8Have you ever used JavaScript templating? If so, what libraries have you used?
Libraries used
- Handlebars, Underscore/Lodash templates, AngularJS, JSX.
Notes
- JSX is concise and type-friendly; AngularJS string-heavy templates are prone to typos.
- ES2015 template literals work for simple templates but do not escape by default.
Example
const name = 'Ada';
const template = `<div>My name is: ${name}</div>`;
// Beware: interpolation is not escaped — sanitize user input to prevent XSS."Explain ""hoisting""."
Hoisting is a JavaScript mechanism where variables and function declarations are moved to the top of their scope before code execution. Remember that JavaScript only hoists declarations, not initialisation.
Example
// Function declarations are hoisted
hoisted(); // works
function hoisted() {}
// var is hoisted (initialized to undefined)
console.log(a); // undefined
var a = 1;
// let/const are in the Temporal Dead Zone
// console.log(b); // ReferenceError
let b = 2;Describe event bubbling.
When an event triggers on a DOM element, it is handled on that element and then bubbles up through ancestors to the document. Bubbling enables event delegation.
<ul id="list">
<li>Item</li>
</ul>
<script>
document.getElementById('list').addEventListener('click', (e) => {
// Delegate: handle clicks on child <li> elements
if (e.target.tagName === 'LI') {
console.log('Clicked:', e.target.textContent);
}
});
</script>"What's the difference between an ""attribute"" and a ""property""?"
Attributes are defined in HTML markup; properties are defined on the DOM node. Example:
<input type="text" value="Hello">const input = document.querySelector('input');
console.log(input.getAttribute('value')); // Hello
console.log(input.value); // Hello
// After changing the field value to "World!"
console.log(input.getAttribute('value')); // Hello
console.log(input.value); // Hello World!What is the difference between == and ===?
== is the abstract equality operator; === is the strict equality operator. == compares after type conversion; === does not convert types.
Examples of == pitfalls:
1 == '1'; // true
1 == [1]; // true
1 == true; // true
0 == ''; // true
0 == '0'; // true
0 == false; // trueAdvice: avoid == except when comparing against null or undefined for convenience.
var a = null;
console.log(a == null); // true
console.log(a == undefined); // trueWhy is it, in general, a good idea to leave the global scope of a website as-is and never touch it?
Every script has access to the global scope, and if everyone uses the global scope to define their variables, collisions will likely occur
Explain what a single page app is and how to make one SEO-friendly.
Definition
- A Single Page Application (SPA) uses client-side rendering; navigation updates the URL without full page reloads.
Benefits
- Responsive navigation without flash between pages.
- Fewer repeated asset downloads; clearer client/server separation.
Downsides
- Heavier initial load.
- Requires server routing to a single entry point.
- Content relies on JS execution, which can hurt SEO if crawlers don’t run JS.
SEO-friendly approaches
- Server-Side Rendering (SSR) or Static Site Generation (SSG).
- Pre-rendering services (e.g., Prerender.io) to serve HTML to crawlers.
- Ensure metadata: dynamic
<title>,<meta>tags, canonical links. - Generate sitemap and use structured data where appropriate.
What are the pros and cons of using Promises instead of callbacks?
Pros
- Avoids callback hell; supports readable chaining via
.then(). - Easy parallelism with
Promise.all. - Safer semantics: avoids early/late/multiple callback invocation and error swallowing.
Cons
- Slightly more complex semantics for beginners.
- Requires polyfills in older environments.
What is Promises?
Definition
- A Promise represents a future value:
pending→fulfilledorrejected. then/catchreturn new promises, enabling chaining.
Example
const fetchData = () => new Promise((resolve, reject) => {
setTimeout(() => resolve('data'), 100);
});
fetchData()
.then(v => v.toUpperCase())
.catch(err => console.error(err));What tools and techniques do you use for debugging JavaScript code?
Tools
- Chrome DevTools (sources, network, performance)
- React DevTools, Redux DevTools; Vue DevTools
Techniques
debuggerstatements to pause execution.- Structured
console.*logging; log levels and grouping. - Narrow repro cases; isolate async flows and side effects.
Explain the difference between mutable and immutable objects.
Definitions
- Mutable: state can change after creation.
- Immutable: state cannot change after creation.
Built-in
- Primitives like numbers and strings are immutable; regular objects are mutable.
Approaches
// Constant property
const myObject = {};
Object.defineProperty(myObject, 'number', {
value: 42,
writable: false,
configurable: false,
});
// Prevent extensions
const obj = { a: 2 };
Object.preventExtensions(obj);
obj.b = 3; // ignored or TypeError in strict mode
// Seal
const sealed = Object.seal({ a: 1 }); // no adding/removing, can change values
// Freeze
const frozen = Object.freeze({ a: 1 }); // no adding/removing/changingExplain the difference between synchronous and asynchronous functions.
Synchronous
- Blocks until work completes; code runs in order.
Asynchronous
- Returns immediately; completion handled via callbacks/promises/async-await.
- Keeps UI responsive in browsers.
Example
console.log('A');
setTimeout(() => console.log('B'), 0);
console.log('C');
// Output: A, C, BWhat is event loop? What is the difference between call stack and task queue?
Event loop
- Monitors the call stack; when empty, dequeues tasks from queues to execute.
Queues
- Macro-task queue:
setTimeout, I/O callbacks. - Micro-task queue: promises (
then/catch),queueMicrotask— runs before macro-tasks between ticks.
Example
console.log('start');
setTimeout(() => console.log('timeout'), 0);
Promise.resolve().then(() => console.log('microtask'));
console.log('end');
// start, end, microtask, timeoutWhat are the differences between variables created using let, var or const?
Scope
var: function-scoped.let/const: block-scoped.
function foo() {
var a = 1; let b = 2; const c = 3;
}
// a,b,c not accessible outsideHoisting
varis hoisted and initialized toundefined.let/constare hoisted but in Temporal Dead Zone until declared.
console.log(v); // undefined
var v = 'v';
// console.log(l); // ReferenceError
let l = 'l';Redeclaration & reassignment
varallows redeclaration;let/constdo not.letallows reassignment;constdoes not.
var x = 'x'; var x = 'x2'; // ok
let y = 'y'; // let y = 'y2'; // SyntaxError
const z = 'z'; // z = 'z2'; // TypeErrorJavaScript (ES5) vs ES6
Summary
- ES6 (2015) introduced major features atop ES5:
let/const, arrow functions, classes, template literals, destructuring, spread/rest, modules (import/export), promises, default parameters. - Largely backward compatible; improves scoping, async handling, and code organization.
What is the Temporal Dead Zone
The Temporal Dead Zone is a behavior in JavaScript that occurs when declaring a variable with the let and const keywords, but not with var. The time span between the creation of a variable’s binding and its declaration, is called the temporal dead zone.
Example
// Access before declaration throws
// console.log(a); // ReferenceError
let a = 1;What is heap
Heap(Or memory heap) is the memory location where objects are stored when we define variables.
What is a microTask queue
Microtask queue processes tasks (e.g., promise callbacks) before the macrotask/callback queue between event loop ticks.
setTimeout(() => console.log('macro'), 0);
Promise.resolve().then(() => console.log('micro'));
// Output: micro, macroWhat is babel
Babel is a JavaScript transpiler to convert ECMAScript 2015+ code into a backwards compatible version of JavaScript in current and older browsers or environments
What is the difference between Function constructor (new Function) and function declaration
new Function creates functions in the global scope and does not close over local variables; declarations/expressions do close over outer scopes.
function outer() {
const secret = 1;
const f1 = function () { return secret; }; // closes over secret
const f2 = new Function('return typeof secret'); // 'undefined'
return [f1(), f2()];
}
console.log(outer()); // [1, 'undefined']What is the difference between function and class declaration
Hoisting
- Function declarations are hoisted.
- Class declarations are hoisted but not initialized; accessing before definition throws.
foo(); // ok
function foo() {}
// new Bar(); // ReferenceError: Cannot access 'Bar' before initialization
class Bar {}What are the different kinds of generators
Kinds
- Generator function declaration
- Generator function expression
- Generator method in object literal
- Generator method in class
- Computed property generator (e.g.,
Symbol.iterator)
function* decl() { yield 1; yield 2; }
const expr = function* () { yield 1; yield 2; };
const obj = { *gen() { yield 1; yield 2; } };
class C { *gen() { yield 1; yield 2; } }
const iterObj = { *[Symbol.iterator]() { yield 1; yield 2; } };
console.log(Array.from(iterObj)); // [1, 2]What is the difference between setTimeout, setImmediate and process.nextTick?
Node.js
setTimeout(cb, ms): schedule after delay (macrotask).setImmediate(cb): schedule after current poll phase completes (macrotask, often after I/O).process.nextTick(cb): schedule microtask; runs before other queued work — use sparingly to avoid starvation.
debounce vs throttle
Definitions
- Debounce: delay execution until events stop for
nms. - Throttle: execute at most once every
nms during a burst of events.
function debounce(fn, wait) {
let t;
return (...args) => {
clearTimeout(t);
t = setTimeout(() => fn(...args), wait);
};
}
function throttle(fn, wait) {
let last = 0;
return (...args) => {
const now = Date.now();
if (now - last >= wait) { last = now; fn(...args); }
};
}"""1"" + true - ""1"""
'1' + true; // '1true' (string concatenation)
'1true' - '1'; // NaN (numeric subtraction on non-numeric string)"const a = ""abc"" a[2] = ""d"" console.log(a);"
const a = 'abc';
a[2] = 'd';
console.log(a); // 'abc' — strings are immutableconst obj = { name: 'Quang', // showName: function () {} showName(age) { // method console.log(123 ${this.name} ${age}); } } const showName = obj.showName; showName();
const person = { name: 'Anna' };
const obj = {
name: 'Quang',
showName(age) { console.log(`123 ${this.name} ${age}`); }
};
const showName = obj.showName;
showName(); // 123 undefined undefined — plain call, undefined this
showName.call(person, 23); // 123 Anna 23
showName.apply(person, [23]); // 123 Anna 23Arrow function vs function declaration. Give Example
Key differences
- Arrow functions: lexical
this, noarguments, not constructible. - Regular functions: own
this, havearguments, constructible withnew.
const arrow = (...args) => args.length;
function regular() { return arguments.length; }
console.log(arrow(1,2)); // 2
console.log(regular(1,2)); // 2
// new arrow(); // TypeError: arrow is not a constructor
function C() {}
new C(); // okBubbling and Capturing
"Bubbling and capturing (javascript.info) Bubbling and capturing describe the two phases of event propagation in the DOM when an event occurs on an element with ancestors. Bubbling (default): The event starts at the target element and then ""bubbles"" upwards through its parent elements in the DOM hierarchy, triggering event listeners attached to those ancestors along the way. Capturing: The event starts at the root of the DOM and ""captures"" downwards through the ancestors to the target element, triggering event listeners attached to those ancestors before reaching the target. Capturing is enabled by passing true as the third argument to addEventListener(). Both phases contribute to the event flow, allowing for flexible event handling and techniques like event delegation. Capturing happens before bubbling in Event Propagation If event.stopPropagation() is called during the capturing phase, then the event travel stops, no bubbling will occur. Non-bubbling events such as focus, blur, load can be handled by Capturing"
[Array] iterative methods and empty slots
"iterative methods: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#iterative_methods iterative methods behave differently with empty slots sparse arrays: Arrays can contain ""empty slots"" -> Array methods and empty slots: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#array_methods_and_empty_slots"
CommonJS vs ESM
CommonJS (CJS) uses synchronous require() and module.exports syntax, designed for Node.js, while ECMAScript Modules (ESM) use asynchronous import and export syntax, serving as the official JavaScript standard and supporting native browser environments and Node.js. The main distinctions are their syntax, synchronous vs. asynchronous module loading, and compatibility with different environments. ESM is the future standard, offering benefits like tree shaking and better performance, while CommonJS is still prevalent in the existing Node.js ecosystem. CommonJS (CJS) Syntax: Uses require() to import modules and module.exports to export them. Loading: Loads modules synchronously, which can block execution until the module is loaded. Environment: Primarily used in Node.js. Characteristics: Has been the long-standing standard for server-side JavaScript in Node.js. Provides Node-specific variables like **dirname and **filename. ECMAScript Modules (ESM) Syntax: Uses import and export keywords for module management. Loading: Supports asynchronous loading, enabling better parallelism. Environment: Natively supported in modern web browsers and modern Node.js environments. Characteristics: The official, standardized module system for JavaScript. Enables static analysis of dependencies, leading to more efficient tree shaking (dead code elimination). More suitable for modern web applications due to native browser support and performance benefits. Key Differences at a Glance Feature CommonJS (CJS) ECMAScript Modules (ESM) Syntax require() and module.exports import and export Loading Synchronous Asynchronous Standard De facto standard for Node.js Official JavaScript standard Browser Support Not native Native When to Use Which Use CommonJS for: Older Node.js projects or environments where it's the established standard and you prioritize simplicity. Use ESM for: Modern web applications, new Node.js projects, and situations where you need better performance, native browser support, and advanced features like tree shaking.
var vs let vs const
"In JavaScript, var, let, and const are keywords used to declare variables, each with distinct characteristics regarding scope, reassignment, and hoisting. 1. Scope: var: Variables declared with var have function scope or global scope. This means they are accessible throughout the entire function in which they are declared, or globally if declared outside any function.let: Variables declared with let have block scope. They are only accessible within the specific block (e.g., if statements, for loops, or any curly braces {}) where they are defined.const: Similar to let, const also provides block scope. 2. Reassignment: var: Variables declared with var can be reassigned and redeclared within the same scope. let: Variables declared with let can be reassigned, but they cannot be redeclared within the same block scope. const: Variables declared with const cannot be reassigned after their initial assignment. They are used to declare constants or read-only references. However, if a const variable holds an object or array, its properties or elements can be modified, but the variable itself cannot be pointed to a different object or array. 3. Hoisting: var: Variables declared with var are hoisted to the top of their function or global scope. This means they can be accessed before their declaration, though their value will be undefined until the actual assignment. let and const: Variables declared with let and const are also hoisted, but they are subject to the ""Temporal Dead Zone"" (TDZ). This means accessing them before their declaration will result in a ReferenceError. In summary: Use const for values that should not change throughout the program's execution.Use let for variables whose values might need to be reassigned later in the code.Avoid using var in modern JavaScript development due to its less predictable scoping behavior, which can lead to unexpected bugs. let and const offer more controlled and intuitive variable declaration."
Event capturing goes top-down (document → target); bubbling goes bottom-up (target → document). You can choose phase with the third parameter of addEventListener:
el.addEventListener('click', handler, { capture: true }); // capture phase
el.addEventListener('click', handler); // bubble phase (default)NodeJS
NodeJS
What is Node.js? / How does Node.js work?
Node.js is an open-source server side runtime environment built on Chrome's V8 JavaScript engine. It provides an event driven, non-blocking (asynchronous) I/O and cross-platform runtime environment for building server-side applications using JavaScript.
Node.js vs Browser JavaScript
Node.js is a runtime environment for executing JavaScript code on the server-side, while browser JavaScript is a runtime environment for executing JavaScript code in web browsers.
Node.js runs in a single thread, while browser JavaScript runs in multiple threads.
- Runtime
- Node.js runs JavaScript on the server; browsers run it in the client.
- Both execute JavaScript on a single main thread.
- Event loop
- Node: Powered by libuv . Offloads I/O (FS, DNS, zlib, some crypto) to the kernel or the libuv thread pool (default 4 threads), then queues callbacks back to the main JS thread. This makes I/O appear concurrent without multithreaded JS.
- Browser: Event loop is integrated with rendering and input queues. Long-running JS blocks rendering and user interactions, causing UI freezes.
- “Multithreading”
- Node: JS itself is single-threaded, but the runtime uses extra threads for I/O under the hood. For CPU-bound work, use worker_threads .
- Browser: Main JS thread is single-threaded; other threads handle rendering, networking, and GC. Use Web Workers for heavy computation off the main thread.
- Practical implications
- Node: Never block the event loop; use async I/O (callbacks, promises, async / await ) and offload CPU-bound work to workers.
- Browser: Keep tasks small to maintain UI responsiveness; rely on async APIs and Web Workers for heavy tasks.
- Summary
- Node: Single-threaded JS + libuv thread pool for I/O → efficient concurrency for I/O-heavy workloads.
- Browser: Single main JS thread + rendering/UI constraints → prioritize non-blocking code and off-main-thread computation for smooth UX.
What is Node.js Single Process Model?
Node.js runs in a single process and the application code runs in a single thread and thereby needs less resources than other platforms. This single thread doesn't have to wait for the request to complete and is free to handle the next request.
What are the data types in Node.js?
Just like in JavaScript, Node.js has two broad categories of data types:
- Primitives:
string,number,bigint,boolean,undefined,null,symbol. - Objects:
Object,Function,Array, and Node-specificBuffer.
Node.js includes an additional data type called Buffer (not available in browser JavaScript). Buffers store binary data, commonly used for file I/O and network packets.
Example:
const buf = Buffer.from('hello');
console.log(buf); // <Buffer 68 65 6c 6c 6f>How to create a simple server in Node.js that returns Hello World?
- Create a project directory and enter it:
mkdir myapp
cd myapp- Initialize the project:
npm init -yOptionally set the entry point to app.js.
- Install Express:
npm install express- Create
app.js:
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000, () => {
console.log('Example app listening on port 3000!');
});- Run the app:
node app.jsWhat does the runtime environment mean in Node.js?
The Node.js runtime is the software stack responsible for installing your web service's code and its dependencies and running your service. The runtime environment is literally just the environment your application is running in. This can be used to describe both the hardware and the software that is running your application. How much RAM, what version of node, what operating system, how much CPU cores, can all be referenced when talking about a runtime environment.
Explain usage of NODE_ENV?
NODE_ENV is an environment variable commonly used to control configuration (e.g., development, production). Your app can check its value and change behavior accordingly.
Example:
NODE_ENV=production node app.jsif (process.env.NODE_ENV === 'production') {
// enable production optimizations
}What are the core modules of Node.js?
They are defined within the Node.js source and are located in the lib/ folder, and Node.js has several modules compiled into the binary such as fs, os, path, util, http
What is callback function in Node.js?
In node.js, we basically use callbacks for handling asynchronous operations like — making any I/O request, database operations or calling an API to fetch some data. Callback allows our code to not get blocked when a process is taking a long time.
How assert works in Node.js?
In Node.js, assert is used to write tests. It only provides feedback only when any of the running test cases fails. This module was built to be used internally by Node.js.
What is an error-first callback?
Error-first callbacks use the signature (err, data). If an error occurs, err is non-null and should be handled; otherwise data contains the result.
Example:
const fs = require('fs');
fs.readFile('file.json', (err, data) => {
if (err) {
console.error(err);
return;
}
console.log(data);
});List down the major benefits of using Node.js?
What is package.json?
The package.json file in Node.js is the heart of the entire application. It is basically the manifest file that contains the metadata of the project where we define the properties of a package.
What do you understand by Event-driven programming?
That means instead of waiting for a response javascript will keep executing while listening for other events.
What is an Event loop in Node.js and how does it work?
The Node.js event loop enables non-blocking I/O on a single thread. Async tasks are offloaded (via libuv) and their callbacks are queued for later execution.
Core components:
- Call Stack: executes synchronous code (LIFO).
libuv: handles OS-level async I/O, timers, thread-pool work.- Callback queues: separate queues per phase (timers, I/O, check, close).
- Microtask queues:
process.nextTickand Promise callbacks (higher priority).
Event loop phases (simplified order):
- Timers:
setTimeout,setInterval. - Pending Callbacks: system-level callbacks from previous cycle.
- Idle/Prepare: internal.
- Poll: I/O events; may block waiting for new events.
- Check:
setImmediatecallbacks. - Close Callbacks: e.g.,
socket.on('close').
- Timers:
Microtasks priority:
- After each phase and after initial sync code, drain
process.nextTickand Promise microtasks completely before moving on.
- After each phase and after initial sync code, drain
Example:
console.log('Start');
setTimeout(() => {
console.log('setTimeout');
}, 0);
Promise.resolve().then(() => {
console.log('Promise');
});
setImmediate(() => {
console.log('setImmediate');
});
console.log('End');Typical output:
StartEndPromise(microtask)setTimeout(timers phase) orsetImmediate(check phase) — order can vary depending on system conditions;setImmediatealways runs in the check phase.
Explain REPL in the context of Node.js.
<!-- id: Q~d4(wBr, noteType: Basic-66869 -->
REPL in Node.js stands for Read, Eval, Print, and Loop. It represents a computer environment such as a window console or Unix/Linux shell where any command can be entered and then the system can respond with an output. Node.js comes bundled with a REPL environment by default. REPL can perform the below-listed tasks:Read: Reads the user’s input, parses it into JavaScript data-structure and then stores it in the memory.Eval: Receives and evaluates the data structure.Print: Prints the final result.Loop: Loops the provided command until CTRL+C is pressed twice.
What is module in Node.js?
Modules refer to small units of independent, reusable code. It is used to encapsulate all the related codes or functions into a single file.
Explain libuv.
Libuv is a multi-platform support library of Node.js which majorly is used for asynchronous I/O. A few of the important features of libuv are event loop, Asynchronous file & network operations. FYI, it also supports to handle the child processes
Explain the purpose of ExpressJS package?
Express.js is a framework built on top of Node.js that facilitates the management of the flow of data between server and routes in the server-side applications. Express.js is developed on the middleware module of Node.js called connect. The connect module further makes use of http module to communicate with Node.js.
Differentiate between process.nextTick() and setImmediate()?
Similarities:
- Both schedule callbacks asynchronously.
Differences:
process.nextTick: runs before the next event loop phase (microtask queue), often immediately after current operation finishes.setImmediate: runs in the "check" phase, after I/O events in the current loop iteration.
How does Node.js handle the child threads?
In general, Node.js is a single threaded process and doesn’t expose the child threads or thread management methods. But you can still make use of the child threads for some specific asynchronous I/O tasks which execute in the background.
Explain stream in Node.js along with its various types.
Streams let you process data chunk-by-chunk without loading it all into memory. Useful for large files and network data.
Types:
- Readable: read from a source.
- Writable: write to a destination.
- Duplex: both read and write.
- Transform: duplex that transforms data as it passes through.
List down the various timing features of Node.js.
Reference: https://nodejs.org/en/learn/asynchronous-work/event-loop-timers-and-nexttick
Timing APIs:
setTimeout/clearTimeout: run after N milliseconds.setInterval/clearInterval: run repeatedly every N milliseconds.setImmediate/clearImmediate: run in the event loop "check" phase.process.nextTick: run before the next event loop phase (microtask queue).
What do you understand by an Event Emitter in Node.js?
EventEmitter is a Node.js class that includes all the objects that are capable of emitting events. These objects contain an eventEmitter.on() function which can attach more than one function to the named events that are emitted by the object. Whenever an EventEmitter object throws an event (use evenEmitter.emit()), all the attached functions to that specific event are invoked synchronously.
Module resolution and node_modules scanning
For require('foo'), Node.js searches node_modules directories starting from the current folder up through parent directories until the filesystem root.
Example search order for /home/user/project/app.js requiring bar:
/home/user/project/node_modules/bar/home/user/node_modules/bar/home/node_modules/bar/node_modules/bar
File-Based Module characteristic
Characteristics:
- Conditional loading:
requirecan be called inside code paths. - Blocking:
requireis synchronous; it blocks until the module loads. - Caching: modules are cached by resolved path after first load; subsequent
requirereturns the cachedmodule.exports.
Types of modules? The require order?
- Core module:
require('fs') - File-based module:
require('../foo') - Folder-based module:
require('../foo'),require('../foo/index') - Module in
node_modules:require('foo') - Folder with
package.jsonandmainfield - Folder with
index.js
If more than one case matches, the priority follows the above order.
main vs exports in package.json
In package.json, these fields define how consumers resolve your package:
main: CommonJS entry point (require()in Node).module: ES module entry (used by bundlers supporting ESM).browser: browser-specific entry or file map overrides.types(ortypings): TypeScript declaration file path.exports: modern field for conditional and subpath exports; takes precedence overmain/modulewhen present.
Highlights of exports:
- Conditional exports: different files for
node,browser,import,require. - Subpath exports: expose controlled internal files.
- Encapsulation: hide files not exported.
Fallback/priority (simplified):
exports>browser>module>maintypesresolution may be specified inexportsconditions; otherwise top-leveltypesapplies.
HTML/CSS
HTML/CSS
What is the difference between an id and a class in HTML/CSS?
An id is a unique identifier for a single HTML element. A class is a reusable identifier that can be applied to multiple elements.
In CSS, an id is selected using the # symbol, while a class is selected using the . symbol.
Can you explain the box model in CSS?
The CSS box model describes the rectangular boxes generated for elements in the DOM. The box model is composed of the following layers:
Content: The innermost part, where text and images appear.
Padding: The space between the content and the border.
Border: The outer edge of the padding, surrounding the element.
Margin: The space outside the border, separating the element from others.
What is the difference between inline, inline-block, and block elements?
In CSS, the difference between inline, inline-block, and block elements is on the way they’re rendered in the web page:
Inline: Inline elements don’t have a width or height. They don’t start on a new line and take up only the width that’s required (based on their content). Examples: <span>, <a>.
Inline-block: Do not start on a new line, but allow you to set height and width. Example: <img>.
Block: Elements start on a new line, taking up the full width available by default. Their width and height can be set. Examples: <div>, <p>.
What is the difference between the em and rem units?
They’re both relative units of measurement, however, they’re relative to different things:
“em” units are relative to the font size of their parent element. So if the parent element has a font size of 20px, then setting a “2em” font size, would equal to 40px.
“rem” units are “root em”, which means they’re relative to the web page’s root element (the <html> element).
Flexbox vs Grid vs Box Layout
Flexbox is a one-dimensional layout model that arranges items in a row or a column. It’s best used for smaller layout changes, like aligning items in a navigation bar or a footer.
Grid is a two-dimensional layout model that arranges items in rows and columns. It’s best used for larger layout changes, like creating a responsive grid layout for a website.
Box Layout is the default layout model in CSS. It’s based on the box model, where each element is a rectangular box. It’s best used for simple layouts, like centering an element on the page.
Can you explain CSS specificity and how it works?
What are media queries?
Explain some of the pros and cons for CSS animations versus JavaScript animations.
Use CSS animations for simpler “one-shot” transitions, like toggling UI element states. Use JavaScript animations when you want advanced effects like bouncing, stop, pause, rewind, or slowing down. If you choose to animate with JavaScript, use the Web Animations API or a modern framework you’re comfortable with.
"Css Selector: ~, >, +, #, ."
div p /* Selects all <p> elements inside <div> elements */
p.intro /* Selects all <p> elements with class="intro" */
#firstname /* Selects the element with id="firstname" */
.name1.name2 /* Selects elements with both name1 and name2 classes */
.name1 .name2/* Selects descendants with name2 under an element with name1 */
div > p /* Selects <p> elements whose parent is a <div> */
div + p /* Selects the first <p> immediately after a <div> */
p ~ ul /* Selects all <ul> elements placed after a <p> */Reference: CSS Selectors Reference (w3schools.com).
css vs css-in-js
tailwindcss vs css
sass vs postcss
Operation System
Operation System
What do you mean by an operating system?
An Operating System (OS) is system software that manages computer hardware and software resources and provides common services for programs.
- Manages CPU, memory, storage, I/O devices, and processes.
- Schedules tasks and allocates resources fairly and efficiently.
- Provides abstractions (files, processes, threads) and security.
- Acts as an intermediary between users/applications and hardware.
Scheduling Algorithm
Common CPU scheduling algorithms:
- FCFS (First Come First Serve): processes execute in arrival order; easy to implement (FIFO queue) but may have high average waiting time.
- SJF/SJN (Shortest Job First/Next): runs the process with the smallest burst time; minimizes average waiting time; may cause starvation for long jobs.
- Priority Scheduling: runs the highest priority process first; equal priorities use FCFS; risk of starvation for low-priority processes (can use aging).
- SRTF (Shortest Remaining Time First): preemptive version of SJF; always runs the job with the shortest remaining time; good for short jobs; can preempt longer jobs.
- Round Robin (RR): each process gets a fixed time slice (quantum); preempted after quantum expires; improves responsiveness in time-sharing systems.
Difference between Counting and Binary Semaphores
- Binary semaphore: takes values 0/1; used for mutual exclusion (mutex-like behavior).
- Counting semaphore: holds a non-negative integer; controls access to a resource pool with multiple instances.
- Binary semaphores are simpler and enforce exclusive access; counting semaphores manage capacity.
What is Deadlock?
Deadlock occurs when processes are blocked, each holding a resource and waiting for others to release theirs.
Necessary conditions (Coffman):
- Mutual exclusion
- Hold and wait
- No preemption
- Circular wait
Ram vs Cache
- Cache: very fast, small memory close to the CPU; stores frequently used data/instructions; organized in levels (L1/L2/L3).
- RAM: larger main memory; stores programs and data currently in use; slower than cache but faster than disk.
Thread vs Process
- Process: an executing program with its own memory space.
- Thread: lightweight execution unit within a process; shares process memory.
Multi-thread vs multi-process
- Multiprocessing: multiple processes (often across CPUs/cores) with isolated memory; improves parallelism and isolation; IPC required.
- Multithreading: multiple threads within one process sharing memory; lower overhead; easier sharing; needs careful synchronization.
Virtual Memory (VM), VM paging and Page Fault
- Virtual Memory: abstraction that gives processes the illusion of a large, contiguous memory space; enables memory protection and isolation.
- Paging: divides virtual memory into fixed-size pages mapped to physical frames; avoids external fragmentation.
- Page Fault: occurs when a process accesses a page not in physical memory; OS loads the page from disk (swap/page file) into RAM.
Ram vs Rom
- RAM (Random Access Memory): volatile; temporary working memory for active programs/data.
- ROM (Read-Only Memory): non-volatile; permanently stores firmware/instructions.
Solution to the Critical Section Problem
- A correct solution must satisfy:
- Mutual Exclusion: only one process in the critical section at a time.
- Progress: if no process is in the critical section, selection of the next entrant cannot be postponed indefinitely.
- Bounded Waiting: each process has a bounded waiting time before entering the critical section.
General
General
Semantic Versioning
Semantic versioning means versioning your software in a way that the version numbers have significant meaning. Node.js developers follow a three-digit versioning scheme: MAJOR.MINOR.PATCH.
Optimistic UI Design
Updates the UI based on predictable states immediately, without waiting for the data response. The response time should be less than 2 seconds.
Atomic design methodology
Atomic design is a methodology composed of five distinct stages working together to create interface design systems in a more deliberate and hierarchical manner.
The five stages of atomic design are:
- Atoms: elemental UI building blocks.
- Molecules: collections of atoms forming simple UI components.
- Organisms: complex UI components composed of groups of molecules and/or atoms and/or other organisms.
- Templates: place components into a layout and demonstrate the design’s underlying content structure.
- Pages: apply real content to templates to demonstrate the final UI and test.
What are Micro Frontends? Pros and cons
Micro frontends are a pattern where web application UIs are composed from semi-independent fragments. Fragments can be built by different teams using different technologies.
Advantages:
- Team scalability.
- Strategic vs tactical focus.
- Reusability.
- Multiple frameworks.
Disadvantages:
- Complexity (communication, development, deployment).
- No standards.
- Increased payloads.
SQL vs noSQL database
SQL is the programming language used to interface with relational databases. NoSQL is a class of DBMs that are non-relational and generally do not use SQL.
Consistency, Availability and Partition Tolerance Trade offs
Tradeoff between consistency, availability, and latency exists even when there are no network partitions. Reason for the tradeoff is that a high availability requirement implies that the system must replicate data.
Monolith Repo?
An app architecture for managing multiple packages from your local file system within a singular top-level, root package. Dependencies can be linked together, which is a better mechanism than yarn link. All your project dependencies are installed together.
How do you handle state management in single-page applications?
Without a full framework or library like React or Vue.js, properly handling state management is not a trivial task.
Some options available through the language itself are:
- Global variables: Centralize state in global variables or a global object. This can become unmanageable for large applications and makes local state harder to maintain.
- Module pattern: Encapsulate state and provide a clear API to manage it. Instantiate local instances for individual components.
- Pub/Sub pattern: Decouple state changes using event-driven architecture. More complex, but flexible.
- State management libraries: Use Redux or similar libraries even without frameworks.
Popular State Managements
- Redux: predictable state container.
- Zustand: state management using simplified Flux principles; store is a hook usable anywhere, no provider needed.
- RxJS: library for reactive programming using Observables.
- React Query: data-fetching library for React; handles fetching, caching, synchronizing, and updating server state.
How to write effective unit test
- Test small pieces of code in isolation.
- Follow Arrange–Act–Assert.
- Keep tests short and simple.
- Cover happy path first, then test edge cases.
- Write tests before fixing bugs.
- Make them performant.
- Keep them stateless and consistent.
- Use descriptive names.
What is Bundler? Webpack vs Rollup vs Parcel
CommonJS vs RequireJS (AMD) vs ES6 module
- CommonJS: synchronous module loading; browsers cannot use directly without transpiling.
- AMD (RequireJS): asynchronous module loading; usable in browsers.
- ES6 modules: native JS modules; both sync and async loading; older browsers need a transpiler like Babel.
Webpack properties: entry, output, resolve, module, plugins
npx webpack takes an entry script as entry point and generates output as configured.
- resolve: configure how modules are resolved.
- alias: use aliases instead of relative import paths.
- extensions: resolve extensions in order; use
'...'to include defaults.
- module: determine how different types of modules are treated.
- rules: apply loaders or modify the parser when creating modules.
- plugins: array of webpack plugins; allow different behavior between development and release builds.
Babel webpack plugins: @babel/core, @babel/plugin-transform-runtime, @babel/preset-env, @babel/preset-react
TypeScript configurations
Monorepo vs MultiRepo
Should my component library be a monorepo? | Mae Capozzi's Blog
What is tree shaking, and how does it help with the performance of a web application?
Tree shaking is a technique used in JavaScript module bundlers, like Webpack or Vite, to remove unused code from the final bundled output.
Main benefits include:
- Reduced bundle size: removes unused code, improves load times and reduces bandwidth usage.
- Improved performance: smaller bundles parse and execute faster, improving responsiveness.
- Better resource utilization: write modular code without unused dependencies bloating the final bundle.
Functional Programming
Functional programming builds software by composing pure functions, avoiding shared state, mutable data, and side effects. It is declarative rather than imperative, and application state flows through pure functions. Reference: Fundamentals of functional programming with React - LogRocket Blog.
OOP (Object-oriented programming)
Refactoring/Code Review
- Move code to where it most logically belongs.
- Remove duplicate code.
- Make names self-documenting.
- Split methods into smaller pieces.
- Re-arrange inheritance hierarchies. Reference: Refactoring: clean your code.
Code Review checklist
Should:
- Identify obvious bugs.
- Look for possible security issues.
- Look for “clever” code that reduces readability or maintainability.
- Check for code duplication.
- Check for adherence to the team’s standardized process.
- Check whether names are descriptive enough.
- Look for possible performance improvements (expensive operations inside loops, excessive object allocations, inefficient string concatenations, inefficient logging).
- Check the presence and quality of tests:
- Presence: Did the author create tests for their change?
- Quality: Do the tests effectively exercise the system under test and follow best practices?
- Readability: Tests are documentation; they should be simple and easy to understand.
- Naming: Are tests named according to the team’s convention and easy to understand?
- Explain your changes.
- Optional: add code documentation.
Should not:
- Focus on cosmetic concerns.
- Rely on manual testing alone.
- Mismatch standardized processes between different team members.
Reference: What You Need in a Code Review Checklist (& What You Don't) - LinearB.
Test Driven Development (TDD) Cycle
- Add a test.
- Run all tests; the new test should fail for expected reasons.
- Write the simplest code that passes the new test.
- Run all tests; they should now pass.
- Refactor as needed, using tests after each refactor to ensure functionality is preserved.
- Repeat from step 1.
Development cycle:
- Write tests first.
- Each test case fails initially.
What is API gateway?
An API gateway is an API management tool that sits between a client and a collection of backend services. It acts as a reverse proxy to accept all API calls, aggregate the various services required to fulfill them, and return the appropriate result. When a client makes a request, the API gateway breaks it into multiple requests, routes them to the right places, produces a response, and keeps track of everything. Reference: What does an API gateway do? (redhat.com).
Design Patterns
Design Patterns
Singleton Pattern
Share a single global instance throughout our application.
In React, we often rely on a global state through state management tools such as Redux or React Context instead of using Singletons. Although their global state behavior might seem similar to that of a Singleton, these tools provide a read-only state rather than the mutable state of the Singleton.
Proxy Pattern
Intercept and control interactions to target objects. Proxy can help with validation, formatting, notifications, or debugging. The two most common methods of Proxy handler are get and set.
Provider Pattern/Context API
Makes it possible to pass data to many components, without having to manually pass it through each component layer.
Export and Import in ES6
There are two different types of export: named and default. You can have multiple named exports per module but only one default export. Named exports are useful to export several values. During the import, it is mandatory to import them within curly braces with the same name of the corresponding object. But a default export can be imported with any name.
Re-Export/Aggregating (Export From):
export * from '…'; // does not set the default export
export * as name1 from '…'; // ECMAScript® 2020
export { name1, name2, nameN } from '…';
export { import1 as name1, import2 as name2, nameN } from '…';
export { default, /* others */ } from '…';Hook vs HOC
Best use-cases for a HOC: The same, uncustomized behavior needs to be used by many components throughout the application. The component can work standalone, without the added custom logic.
Best use-cases for Hooks: The behavior has to be customized for each component that uses it. The behavior is not spread throughout the application; only one or a few components use the behavior. The behavior adds many properties to the component.
Reference: HOC Pattern (patterns.dev)
TypeScript
TypeScript
Generic Type
Generics let you parameterize types so they can be reused across different shapes.
Common generic utilities and examples:
Array<ItemType>Promise<ReturnedType>Readonly<T>Partial<T>Record<KeyType, ValueType>
Example:
function wrap<T>(value: T): { data: T } {
return { data: value };
}
const r1 = wrap<string>('hello');
const r2 = wrap(123); // T is inferred as numberWhat are the primitive types in TypeScript?
string,number,boolean,bigint,symbol,null,undefined.
What is any type, and when to use it?
anydisables type checking for a value. Use sparingly.- Implicit
anycan occur when the compiler cannot infer a type and no annotation is provided. - Prefer
unknownor specific types to keep safety.
What is void, and when to use the void type?
voidindicates a function returns no value.
function log(msg: string): void {
console.log(msg);
}What is an unknown type, and when to use it in TypeScript?
unknownis a type-safe counterpart ofany.- You can assign anything to
unknown, but you must narrow it before using it.
function handle(input: unknown) {
if (typeof input === 'string') {
// narrowed to string
console.log(input.toUpperCase());
}
}Note to Create Strongly typed Component Events and Event Handlers
- Inline event handlers often infer correct types automatically.
- Named handlers may require explicit annotations.
- Tip: hover handlers in your editor to see inferred types.
function Input() {
const onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
console.log(e.key);
};
return <input type="text" onKeyDown={onKeyDown} />;
}"<input type=""text"" onKeyDown={e:React.KeyboardEvent<HTMLInputElement> => console.log(e.key)} /> What is wrong?"
You must wrap the parameter and annotation in parentheses.
Correct:
<input
type="text"
onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>) => console.log(e.key)}
/>declare type for actions and dispatchs of redux-thunk
import { AnyAction } from 'redux';
import { ThunkAction, ThunkDispatch } from 'redux-thunk';
type AppState = { /* ... */ };
export type AppThunk<ReturnType = void> = ThunkAction<
ReturnType,
AppState,
unknown,
AnyAction
>;
export type AppDispatch = ThunkDispatch<AppState, unknown, AnyAction>;declare enum type
enum Status {
Idle = 'idle',
Loading = 'loading',
Success = 'success',
Error = 'error',
}
function setStatus(s: Status) {}
setStatus(Status.Loading);