This is Part 7 of 10, a bonus practice article containing 75 coding interview questions drawn from the React Native Interview Handbook. It covers the implementation tasks commonly used in JavaScript and React Native rounds, from string and array problems to hooks, FlatList, asynchronous work, caching, retries, and native modules.
Complete series
This Dev.to series has five core handbook articles plus five focused practice extras. Open the series page to move through the complete reading order:
- Part 1: JavaScript — core handbook, questions 1–120
- Part 2: React — core handbook, questions 121–220
- Part 3: React Native — core handbook, questions 221–420
- Part 4: Performance & Architecture — core handbook, questions 421–560
- Part 5: Senior & System Design — core handbook, questions 561–719
- Part 6: Output-Based JavaScript Practice — bonus practice article
- Part 7: Coding Interview Practice — bonus practice article
- Part 8: Code Output Challenges — bonus practice article
- Part 9: Current React Native Interview Questions — new high-frequency practice article
- Part 10: Project & Production Interviews — senior project ownership and real-production practice
How to answer coding questions
Before coding, clarify inputs, output, edge cases, platform constraints, time complexity, space complexity, cancellation, and test coverage. Start with a correct readable solution, then optimize only when the constraint justifies it.
Topics covered
- Strings, arrays, maps, sets, recursion, and algorithmic complexity
- Debounce, throttle, memoization, deep cloning, and polyfills
- Custom hooks, API state, error boundaries, and React rendering
-
FlatListpagination, pull to refresh, search, and offline retry - Promises, timeouts, concurrency limits, and exponential backoff
- Caching, EventEmitter, Pub/Sub, LRU design, and native module boundaries
Interview coding checklist
- Confirm assumptions before writing code.
- State time and space complexity.
- Handle empty input, invalid input, and duplicate values deliberately.
- For React Native, discuss loading, errors, cancellation, cleanup, and accessibility.
- Explain how you would test the solution.
Coding Problems
75 reviewed questions.
🟢 Beginner
1. How do you build a character-frequency map?
Code example:Answer
Answer: Iterate characters and increment a count keyed by each character.
const freq = (s) =>
[...s].reduce((m, c) => ((m[c] = (m[c] || 0) + 1), m), {});
2. How do you check whether a string is a palindrome?
Code example:Answer
Answer: Normalize the string and compare it with its reverse.
const isPalindrome = (s) => {
s = s.toLowerCase();
return s === [...s].reverse().join('');
};
3. How do you count vowels in a string?
Code example:Answer
Answer: Match vowels case-insensitively and use zero when there is no match.
const vowels = (s) => (s.match(/[aeiou]/gi) || []).length;
4. How do you find the largest number in an array?
Code example:Answer
Answer: Use Math.max with spread for moderate arrays or scan once for very large arrays.
const max = (a) => Math.max(...a);
5. How do you implement a usePrevious hook?
Code example:Answer
Answer: Store the current value in a ref after commit and return the ref's previous content during render.
const ref = useRef();
useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
6. How do you remove duplicates from an array?
Code example:Answer
Answer: Create a Set from the array and spread it back into an array. This preserves the first occurrence order.
const unique = (a) => [...new Set(a)];
7. How do you reverse a string?
Code example:Answer
Answer: Split into characters, reverse, and join; use Array.from or spread when Unicode code points matter.
const reverse = (s) => [...s].reverse().join('');
🟡 Intermediate
8. Array.prototype.map polyfill (Medium)?
Code example:Answer
Answer: Creates a new array and preserves sparse-array holes.
I include value, index and source arguments, support thisArg, and avoid invoking the callback for missing sparse indexes. A full spec polyfill has additional coercion details.
Array.prototype.myMap = function (callback, thisArg) {
if (this == null) throw new TypeError('Invalid receiver');
const source = Object(this);
const length = source.length >>> 0;
const result = new Array(length);
for (let i = 0; i < length; i++) {
if (i in source) {
result[i] = callback.call(thisArg, source[i], i, source);
}
}
return result;
};
9. Array.prototype.reduce polyfill (Medium)?
Code example:Answer
Answer: Matches core reduce behavior, including a missing initial value.
The important edge case is an empty array without an initial value. I also skip sparse holes and pass all four callback arguments.
Array.prototype.myReduce = function (callback, initialValue) {
const source = Object(this);
const length = source.length >>> 0;
let index = 0;
let accumulator;
if (arguments.length > 1) {
accumulator = initialValue;
} else {
while (index < length && !(index in source)) index++;
if (index >= length) throw new TypeError('Empty array');
accumulator = source[index++];
}
for (; index < length; index++) {
if (index in source) {
accumulator = callback(
accumulator,
source[index],
index,
source,
);
}
}
return accumulator;
};
10. Challenge A: useDebounce?
Code example:Answer
Answer: Keep a debounced value in state, start a timeout whenever the source value or delay changes, and clear the previous timeout in effect cleanup. The hook returns the last value whose delay completed. Tests should cover rapid changes, delay changes, unmount cleanup, and the initial value.
function useDebounce(value, delay = 300) {
const [debounced, setDebounced] = useState(value);
useEffect(() => {
const id = setTimeout(() => setDebounced(value), delay);
return () => clearTimeout(id);
}, [value, delay]);
return debounced;
}
11. Challenge B: Infinite scroll + pull to refresh?
Code example:Answer
Answer: Keep initial loading, pagination, and refresh states separate. Guard onEndReached while a page request is active, deduplicate items by stable identifier, and ignore or cancel stale responses. Refresh resets the cursor and replaces data only after the first-page request succeeds, while pagination appends the next confirmed page.
const loadMore = () => {
if (!loadingMore && hasNextPage) fetchNextPage();
};
12. Challenge C: API hook with loading/error?
Code example:Answer
Answer: I keep data, error, and loading state in a custom hook, run the supplied fetcher in an effect, abort on cleanup, ignore AbortError, and return the three states to the screen.
function useApi(fetcher) {
const [state, setState] = useState({ loading: true });
useEffect(() => {
const controller = new AbortController();
setState({ loading: true });
fetcher(controller.signal)
.then((data) => setState({ data, loading: false }))
.catch((error) => {
if (error.name !== 'AbortError')
setState({ error, loading: false });
});
return () => controller.abort();
}, [fetcher]);
return state;
}
13. Check a normalized palindrome (Easy)?
Code example:Answer
Answer: Expected result: true
Explanation: I clarify whether case, spaces, punctuation and Unicode must be ignored. The two-pointer comparison avoids creating a second reversed string.
function isPalindrome(value) {
const clean = value.toLowerCase().replace(/[^a-z0-9]/g, '');
let left = 0;
let right = clean.length - 1;
while (left < right) {
if (clean[left++] !== clean[right--]) return false;
}
return true;
}
isPalindrome('A man, a plan, a canal: Panama');
14. Check two strings are anagrams without sort (Easy/Medium)?
Code example:Answer
Answer: areAnagrams('listen', 'silent') returns true.
This frequency-map solution avoids O(n log n) sorting. I first confirm normalization rules and mention that this exact style has appeared in React Native coding rounds.
function areAnagrams(a, b) {
const left = a.toLowerCase().replace(/\s/g, '');
const right = b.toLowerCase().replace(/\s/g, '');
if (left.length !== right.length) return false;
const counts = new Map();
for (const char of left) {
counts.set(char, (counts.get(char) ?? 0) + 1);
}
for (const char of right) {
const next = (counts.get(char) ?? 0) - 1;
if (next < 0) return false;
counts.set(char, next);
}
return true;
}
15. Debounce search TextInput?
Code example:Answer
Answer: Update local text immediately and debounce only the search side effect. Clear the previous timer when text changes, cancel the active request when possible, and ignore stale responses so an older query cannot replace newer results.
function SearchInput() {
const [text, setText] = useState('');
const query = useDebounce(text, 300);
useEffect(() => {
if (query) searchApi(query);
}, [query]);
return <TextInput value={text} onChangeText={setText} />;
}
16. Deep clone nested arrays and plain objects (Medium)?
Code example:Answer
Answer: Expected result: Returns an independent nested copy and preserves circular references.
Explanation: I state the supported types. JSON stringify is not a true deep clone because it loses undefined, Date, BigInt and circular references. In modern production code, structuredClone may be appropriate.
function deepClone(value, seen = new WeakMap()) {
if (value === null || typeof value !== 'object') return value;
if (seen.has(value)) return seen.get(value);
if (value instanceof Date) return new Date(value);
const copy = Array.isArray(value) ? [] : {};
seen.set(value, copy);
for (const key of Reflect.ownKeys(value)) {
copy[key] = deepClone(value[key], seen);
}
return copy;
}
17. Find the first non-repeating character (Easy)?
Code example:Answer
Answer: c
The first pass counts; the second preserves original order. I return null explicitly when no unique character exists.
function firstUnique(value) {
const counts = new Map();
for (const char of value) {
counts.set(char, (counts.get(char) ?? 0) + 1);
}
for (const char of value) {
if (counts.get(char) === 1) return char;
}
return null;
}
firstUnique('aabbcddee');
18. Flatten a nested array without flat() (Medium)?
Code example:Answer
Answer: [1, 2, 3, 4, 5]
I explain the recursive base case. For extremely deep input I would use an explicit stack to avoid call-stack overflow.
function flatten(values) {
return values.reduce(
(result, value) =>
result.concat(Array.isArray(value) ? flatten(value) : value),
[],
);
}
flatten([1, [2, [3, 4]], 5]);
19. Flatten object?
Code example:Answer
Answer: Walk the object recursively and build each output key from its parent path and current property. Clarify how arrays, null, dates, separator characters, circular references, and empty containers should be handled.
function flatten(object, parent = '', result = {}) {
for (const [key, value] of Object.entries(object)) {
const path = parent ? `${parent}.${key}` : key;
if (value && typeof value === 'object' && !Array.isArray(value)) {
flatten(value, path, result);
} else {
result[path] = value;
}
}
return result;
}
20. Flatten only to a requested depth (Medium)?
Code example:Answer
Answer: [1, 2, 3, [4]]
I validate depth in production and preserve remaining nested arrays once depth reaches zero. This exact depth-based variation has appeared in a React Native interview report.
function flattenDepth(values, depth = 1) {
if (depth === 0) return values.slice();
return values.reduce((result, value) => {
return result.concat(
Array.isArray(value) ? flattenDepth(value, depth - 1) : value,
);
}, []);
}
flattenDepth([1, [2, [3, [4]]]], 2);
21. Function.prototype.bind polyfill (Medium/Hard)?
Code example:Answer
Answer: Returns a function with fixed context and optional partial arguments.
A good bind answer must discuss constructor usage: new should ignore the bound context. A fully spec-compliant implementation also handles metadata and edge cases.
Function.prototype.myBind = function (context, ...preset) {
const target = this;
function bound(...later) {
const receiver = this instanceof bound ? this : context;
return target.apply(receiver, [...preset, ...later]);
}
bound.prototype = Object.create(target.prototype);
return bound;
};
22. Group objects by a property (Easy/Medium)?
Code example:Answer
Answer: An object whose keys are professions and values are user arrays.
I define behavior for a missing property. In production I may prefer Map if keys are not strings or if prototype-safe storage matters.
function groupBy(items, key) {
return items.reduce((groups, item) => {
const group = item[key] ?? 'unknown';
(groups[group] ??= []).push(item);
return groups;
}, {});
}
groupBy(users, 'profession');
23. How do you add a timeout to a Promise?
Code example:Answer
Answer: Race the operation against a timer Promise that rejects. Clear the timer in a production helper and cancel the underlying operation when possible.
function withTimeout(p, ms) {
return Promise.race([
p,
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Timeout')), ms),
),
]);
}
24. How do you check whether two strings are anagrams?
Code example:Answer
Answer: Normalize both strings and compare sorted characters, or compare frequency maps for linear time.
const anagram = (a, b) =>
[...a].sort().join('') === [...b].sort().join('');
25. How do you find a missing number from 1 through n?
Code example:Answer
Answer: Subtract the array sum from n(n+1)/2, assuming exactly one number is missing and values are valid.
const missing = (a, n) =>
(n * (n + 1)) / 2 - a.reduce((x, y) => x + y, 0);
26. How do you find pairs that sum to a target?
Code example:Answer
Answer: Scan once with a Set of prior values; when target minus the current value has been seen, record the pair.
function twoSum(a, t) {
const seen = new Set(),
out = [];
for (const n of a) {
if (seen.has(t - n)) out.push([t - n, n]);
seen.add(n);
}
return out;
}
27. How do you find the first non-repeating character?
Code example:Answer
Answer: Build a frequency map, then scan the original string and return the first character with count one.
function firstUnique(s) {
const m = freq(s);
for (const c of s) if (m[c] === 1) return c;
}
28. How do you find the longest substring without repeating characters?
Code example:Answer
Answer: Use a sliding window and map each character to its latest index. Move the left edge past a duplicate and track the maximum width.
function longest(s) {
const seen = new Map();
let l = 0,
b = 0;
for (let r = 0; r < s.length; r++) {
if ((seen.get(s[r]) ?? -1) >= l) l = seen.get(s[r]) + 1;
seen.set(s[r], r);
b = Math.max(b, r - l + 1);
}
return b;
}
29. How do you find the maximum subarray sum?
Code example:Answer
Answer: Kadane's algorithm tracks the best subarray ending at each index and the best seen overall in O(n) time.
function maxSubArray(a) {
let cur = a[0],
best = a[0];
for (let i = 1; i < a.length; i++) {
cur = Math.max(a[i], cur + a[i]);
best = Math.max(best, cur);
}
return best;
}
30. How do you find the second-largest distinct number?
Code example:Answer
Answer: Track the largest and second-largest distinct values in one pass, updating both when a new maximum appears.
function secondMax(a) {
let x = -Infinity,
y = -Infinity;
for (const n of a) {
if (n > x) {
y = x;
x = n;
} else if (n > y && n !== x) y = n;
}
return y;
}
31. How do you flatten a nested object?
Code example:Answer
Answer: Recursively visit nested plain objects, joining path segments, and assign leaf values to the output.
function flattenObj(o, p = '', out = {}) {
for (const [k, v] of Object.entries(o)) {
const key = p ? `${p}.${k}` : k;
if (v && typeof v === 'object' && !Array.isArray(v))
flattenObj(v, key, out);
else out[key] = v;
}
return out;
}
32. How do you flatten an array of any depth?
Code example:Answer
Answer: Use flat(Infinity) or recurse into array elements while accumulating scalar values.
const flat = nested.flat(Infinity);
function flatten(a) {
return a.reduce(
(r, v) => r.concat(Array.isArray(v) ? flatten(v) : v),
[],
);
}
33. How do you group an array of objects by a property?
Code example:Answer
Answer: Reduce into an object whose property values are arrays, creating each group on first use.
function groupBy(a, k) {
return a.reduce((m, o) => ((m[o[k]] ??= []).push(o), m), {});
}
34. How do you implement a reusable API hook?
Code example:Answer
Answer: Model data, loading, and error; start work in an effect; abort during cleanup; and ignore abort errors.
function useApi(fetcher) {
const [state, setState] = useState({ loading: true });
useEffect(() => {
const controller = new AbortController();
fetcher(controller.signal)
.then((data) => setState({ data, loading: false }))
.catch((error) => {
if (error.name !== 'AbortError')
setState({ error, loading: false });
});
return () => controller.abort();
}, [fetcher]);
return state;
}
35. How do you implement a theme provider?
Code example:Answer
Answer: Store mode in context, derive theme tokens, expose a toggle, and consume through a focused useTheme hook.
<ThemeContext.Provider value={{theme,mode,toggle}}>
36. How do you implement a useDebounce hook?
Code example:Answer
Answer: Keep a debounced value in state, start a timeout whenever the source value or delay changes, and clear the previous timeout in effect cleanup. The hook returns the last value whose delay completed. Tests should cover rapid changes, delay changes, unmount cleanup, and the initial value.
useEffect(() => {
const id = setTimeout(() => setDebounced(value), delay);
return () => clearTimeout(id);
}, [value, delay]);
37. How do you implement a useThrottle hook?
Code example:Answer
Answer: Track the last publication time, update immediately when the interval has elapsed, otherwise schedule the remaining delay and clean up that timer.
function useThrottle(value, delay) {
const [throttled, setThrottled] = useState(value);
const lastRun = useRef(0);
useEffect(() => {
const remaining = Math.max(
0,
delay - (Date.now() - lastRun.current),
);
const id = setTimeout(() => {
lastRun.current = Date.now();
setThrottled(value);
}, remaining);
return () => clearTimeout(id);
}, [value, delay]);
return throttled;
}
38. How do you implement an Error Boundary?
Code example:Answer
Answer: Use a class component with getDerivedStateFromError for fallback state and componentDidCatch for reporting.
class ErrorBoundary extends React.Component {
componentDidCatch(e, info) {
logError(e, info);
}
}
39. How do you implement debounce for search TextInput?
Code example:Answer
Answer: I keep the raw text in state for the input, then debounce that value with a custom useDebounce hook. A second effect depends on the debounced query and calls the API. That way we do not hit the server on every keystroke.
<TextInput value={text} onChangeText={setText} />;
40. How do you implement debounce?
Code example:Answer
Answer: Keep a timer in a closure, clear it on every call, and schedule the function after the quiet period.
function debounce(fn, wait) {
let t;
return function (...args) {
clearTimeout(t);
t = setTimeout(() => fn.apply(this, args), wait);
};
}
41. How do you implement deep equality?
Code example:Answer
Answer: Return true for identical values, reject incompatible non-objects, compare key counts, then recursively compare corresponding properties. Production code must handle cycles, symbols, prototypes, and special types.
function deepEqual(a, b) {
if (Object.is(a, b)) return true;
if (!a || !b || typeof a !== 'object' || typeof b !== 'object')
return false;
const ka = Object.keys(a),
kb = Object.keys(b);
return (
ka.length === kb.length &&
ka.every((k) => Object.hasOwn(b, k) && deepEqual(a[k], b[k]))
);
}
42. How do you implement infinite scroll with pull-to-refresh?
Code example:Answer
Answer: Track data, page, refresh, and load-more state; replace data on refresh, append on pagination, guard duplicate requests, and provide stable list keys.
<FlatList
data={items}
refreshing={refreshing}
onRefresh={refresh}
onEndReached={loadMore}
renderItem={renderItem}
/>;
43. How do you implement memoize?
Code example:Answer
Answer: Cache results by an argument key and return the cached value on repeated calls. Real implementations need an appropriate key strategy and eviction policy.
function memoize(fn) {
const c = new Map();
return (...a) => {
const k = JSON.stringify(a);
if (c.has(k)) return c.get(k);
const v = fn(...a);
c.set(k, v);
return v;
};
}
44. How do you implement once?
Code example:Answer
Answer: Keep called and result in a closure. Invoke the target only on the first call and return the stored result thereafter.
function once(fn) {
let called = false,
result;
return (...a) => {
if (!called) {
called = true;
result = fn(...a);
}
return result;
};
}
45. How do you implement throttle?
Code example:Answer
Answer: Track the last execution time and invoke only when the minimum interval has elapsed.
function throttle(fn, wait) {
let last = 0;
return function (...args) {
const now = Date.now();
if (now - last >= wait) {
last = now;
fn.apply(this, args);
}
};
}
46. How do you move all zeros to the end of an array?
Code example:Answer
Answer: Write nonzero values forward in one pass, then fill the remaining positions with zeros.
function moveZeroes(a) {
let i = 0;
for (const x of a) if (x !== 0) a[i++] = x;
while (i < a.length) a[i++] = 0;
return a;
}
47. How do you run an array of async functions sequentially?
Code example:Answer
Answer: Use for...of and await each function before starting the next, collecting results in order.
async function sequential(fns) {
const out = [];
for (const fn of fns) out.push(await fn());
return out;
}
48. How do you run-length compress a string?
Code example:Answer
Answer: Scan each run of equal characters, append the character and run length, then continue from the next run.
function compress(s) {
let out = '',
i = 0;
while (i < s.length) {
let j = i;
while (j < s.length && s[j] === s[i]) j++;
out += s[i] + (j - i);
i = j;
}
return out;
}
49. Implement debounce (Medium)?
Code example:Answer
Answer: Expected result: Only the latest call runs after calls stop for delay milliseconds.
Explanation: I preserve this and arguments, and expose cancel for component cleanup. In React Native search, I keep the debounced function reference stable and cancel it on unmount.
function debounce(fn, delay) {
let timer;
function debounced(...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
}
debounced.cancel = () => clearTimeout(timer);
return debounced;
}
50. Implement debounce and throttle?
Code example:Answer
Answer: Debounce clears the previous timer and schedules a new one, so only the final call after quiet time executes. Throttle tracks last execution or a pending timer so calls occur at most once per interval. I preserve this and arguments, expose cancel when useful, and clean it on component unmount.
const debounce = (fn, delay) => {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), delay);
};
};
const throttle = (fn, delay) => {
let ready = true;
return (...args) => {
if (!ready) return;
ready = false;
fn(...args);
setTimeout(() => {
ready = true;
}, delay);
};
};
51. Implement debounce?
Code example:Answer
Answer: Return a wrapper that clears the previous timer and schedules the latest call after the delay while preserving this and arguments. A production implementation should define leading and trailing execution and expose cancel and flush behavior.
function debounce(fn, delay) {
let timer;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}
52. Implement throttle (Medium)?
Code example:Answer
Answer: Expected result: At most one call runs per delay window.
Explanation: This is a leading-only throttle. I explicitly ask whether trailing calls, cancel, flush or maxWait are required because those change the implementation.
function throttle(fn, delay) {
let waiting = false;
return function (...args) {
if (waiting) return;
waiting = true;
fn.apply(this, args);
setTimeout(() => {
waiting = false;
}, delay);
};
}
53. Implement throttle?
Code example:Answer
Answer: Return a wrapper that runs at most once per interval while preserving this and arguments. Track the last execution and optionally schedule the latest trailing call; define leading, trailing, cancel, and flush semantics before coding.
function throttle(fn, delay) {
let ready = true;
return function (...args) {
if (!ready) return;
ready = false;
fn.apply(this, args);
setTimeout(() => {
ready = true;
}, delay);
};
}
54. Implement useDebounce and explain when to use it?
Code example:Answer
Answer: useDebounce returns a value only after it has stopped changing for a delay. I use it for search input and validation to avoid one API call per keystroke. Cleanup clears the previous timeout; that reset behavior is the key difference from throttle.
function useDebounce(value, delay = 300) {
const [debounced, setDebounced] = useState(value);
useEffect(() => {
const id = setTimeout(() => setDebounced(value), delay);
return () => clearTimeout(id);
}, [value, delay]);
return debounced;
}
55. Reverse a string (Easy)?
Code example:Answer
Answer: evitaN tcaeR
I use Array.from instead of split('') because it handles Unicode code points such as many emoji better. A follow-up can ask for an in-place array reversal.
function reverseString(value) {
return Array.from(value).reverse().join('');
}
console.log(reverseString('React Native'));
56. Run async tasks with a concurrency limit (Hard)?
Code example:Answer
Answer: Runs no more than limit tasks simultaneously and preserves result order.
I accept task functions rather than already-started Promises so concurrency can actually be controlled. I ask whether one rejection should fail fast or whether all results should be collected.
async function runLimited(tasks, limit) {
if (limit < 1) throw new RangeError('limit must be positive');
const results = new Array(tasks.length);
let next = 0;
async function worker() {
while (true) {
const index = next++;
if (index >= tasks.length) return;
results[index] = await tasks[index]();
}
}
const workers = Array.from(
{ length: Math.min(limit, tasks.length) },
worker,
);
await Promise.all(workers);
return results;
}
57. Safely access a nested property by path (Easy/Medium)?
Code example:Answer
Answer: Returns the city or Unknown without throwing.
For a fixed known path I prefer optional chaining. A helper is useful for dynamic paths, but production parsing needs clear rules for escaping and unsafe keys.
function get(object, path, fallback) {
const keys = Array.isArray(path)
? path
: path
.replace(/\[(\w+)\]/g, '.$1')
.split('.')
.filter(Boolean);
let current = object;
for (const key of keys) {
if (current == null) return fallback;
current = current[key];
}
return current === undefined ? fallback : current;
}
get(user, 'profile.address.city', 'Unknown');
58. Two Sum?
Code example:Answer
Answer: I scan once with a Map from value to index. For each number I check whether target minus that number was already seen; if yes I return both indices. This is O(n) time and O(n) space, better than the O(n squared) nested-loop solution.
function twoSum(nums, target) {
const seen = new Map();
for (let i = 0; i < nums.length; i++) {
const need = target - nums[i];
if (seen.has(need)) return [seen.get(need), i];
seen.set(nums[i], i);
}
return [];
}
59. What is the difference between debounce and throttle?
Code example:Answer
Answer: Debounce waits until calls stop for a quiet period; throttle limits execution to at most once per interval. Debounce fits search input, while throttle fits continuous scroll updates.
const debouncedSearch = debounce(search, 300);
const throttledScroll = throttle(onScroll, 300);
60. Why is JSON.parse(JSON.stringify(value)) not a general deep clone?
Code example:Answer
Answer: It loses undefined and functions, converts Date to string, Map/Set to empty objects, NaN/Infinity to null, throws on BigInt and cycles, and does not preserve prototypes. Prefer structuredClone or a type-aware clone.
const source = { missing: undefined, createdAt: new Date() };
const clone = JSON.parse(JSON.stringify(source));
console.log(clone); // createdAt is a string; missing is removed
🔴 Senior
61. How do you expose battery level through a native module?
Code example:Answer
Answer: Define a narrow asynchronous typed method, read BatteryManager or the iOS equivalent on the correct queue, resolve a Promise, and expose the generated module contract.
const level = await NativeModules.Battery.getLevel();
console.log(`Battery level: ${level}%`);
62. How do you implement Array.prototype.filter?
Code example:Answer
Answer: Iterate existing indices, call the predicate with the standard arguments and optional thisArg, and push values whose predicate is truthy.
Array.prototype.myFilter = function (cb, thisArg) {
const out = [];
for (let i = 0; i < this.length; i++)
if (i in this && cb.call(thisArg, this[i], i, this))
out.push(this[i]);
return out;
};
63. How do you implement Array.prototype.map?
Code example:Answer
Answer: Iterate existing indices, call the callback with value, index, and source using the optional thisArg, preserve holes, and return a new array.
Array.prototype.myMap = function (cb, thisArg) {
const out = [];
for (let i = 0; i < this.length; i++)
if (i in this) out[i] = cb.call(thisArg, this[i], i, this);
return out;
};
64. How do you implement Array.prototype.reduce?
Code example:Answer
Answer: Use the supplied initial value when present; otherwise find the first existing element or throw for an empty array. Fold remaining existing indices with accumulator, value, index, and source.
Array.prototype.myReduce = function (cb, init) {
let i = 0,
acc;
if (arguments.length > 1) acc = init;
else {
while (i < this.length && !(i in this)) i++;
if (i >= this.length) throw TypeError();
acc = this[i++];
}
for (; i < this.length; i++)
if (i in this) acc = cb(acc, this[i], i, this);
return acc;
};
65. How do you implement Function.prototype.bind?
Code example:Answer
Answer: Capture the target, thisArg, and preset arguments and return a function that applies the target with combined arguments. A production polyfill must also preserve new-constructor behavior.
Function.prototype.myBind = function (ctx, ...pre) {
const fn = this;
return function (...args) {
return fn.apply(ctx, [...pre, ...args]);
};
};
66. How do you implement Promise.all?
Code example:Answer
Answer: Normalize each input with Promise.resolve, preserve index order, count fulfillments, resolve when all complete, and reject on the first rejection. Resolve an empty iterable immediately.
function promiseAll(ps) {
return new Promise((resolve, reject) => {
const a = Array.from(ps),
r = [];
if (!a.length) return resolve([]);
let n = 0;
a.forEach((p, i) =>
Promise.resolve(p).then((v) => {
r[i] = v;
if (++n === a.length) resolve(r);
}, reject),
);
});
}
67. How do you implement Pub/Sub?
Code example:Answer
Answer: Maintain subscriber sets by topic; subscribe adds and returns an unsubscribe function, while publish calls a snapshot of current subscribers.
function bus() {
const m = new Map();
return {
subscribe(t, f) {
const s = m.get(t) || new Set();
s.add(f);
m.set(t, s);
return () => s.delete(f);
},
publish(t, v) {
[...(m.get(t) || [])].forEach((f) => f(v));
},
};
}
68. How do you implement a cycle-safe deepClone?
Code example:Answer
Answer: Return primitives directly, copy special types, register each source object in a WeakMap before recursing, and clone all own keys so cycles reuse the prior copy.
function deepClone(v, m = new WeakMap()) {
if (v === null || typeof v !== 'object') return v;
if (m.has(v)) return m.get(v);
if (v instanceof Date) return new Date(v);
const out = Array.isArray(v) ? [] : {};
m.set(v, out);
for (const k of Reflect.ownKeys(v)) out[k] = deepClone(v[k], m);
return out;
}
69. How do you implement an EventEmitter?
Code example:Answer
Answer: Store listeners by event, let on add and off remove callbacks, emit over a snapshot, and implement once with a wrapper that unsubscribes before invoking.
class EventEmitter {
constructor() {
this.m = Object.create(null);
}
on(e, f) {
(this.m[e] ??= []).push(f);
return this;
}
off(e, f) {
this.m[e] = (this.m[e] || []).filter((x) => x !== f);
}
emit(e, ...a) {
(this.m[e] || []).slice().forEach((f) => f(...a));
}
once(e, f) {
const w = (...a) => {
this.off(e, w);
f(...a);
};
return this.on(e, w);
}
}
70. How do you implement an LRU cache?
Code example:Answer
Answer: Use insertion order in a Map: on get, delete and reinsert the key as most recent; on set, refresh the key and evict the first key when over capacity.
class LRU {
constructor(n = 10) {
this.n = n;
this.m = new Map();
}
get(k) {
if (!this.m.has(k)) return;
const v = this.m.get(k);
this.m.delete(k);
this.m.set(k, v);
return v;
}
set(k, v) {
this.m.delete(k);
this.m.set(k, v);
if (this.m.size > this.n)
this.m.delete(this.m.keys().next().value);
}
}
71. How do you implement inheritance without class syntax?
Code example:Answer
Answer: Call the parent constructor for own fields, set the child prototype to Object.create(parent.prototype), and restore child.prototype.constructor.
function Animal(n) {
this.name = n;
}
Animal.prototype.speak = function () {
return this.name;
};
function Dog(n) {
Animal.call(this, n);
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
72. How do you implement offline retry?
Code example:Answer
Answer: Retry eligible transient network failures with bounded exponential backoff and jitter, then persist a replay-safe mutation in an outbox for reconnect.
async function retry(request, attempts = 3, baseDelay = 200) {
try {
return await request();
} catch (error) {
if (attempts <= 1) throw error;
const delay = baseDelay * 2 ** (3 - attempts);
await new Promise((resolve) => setTimeout(resolve, delay));
return retry(request, attempts - 1, baseDelay);
}
}
73. How do you limit concurrent asynchronous operations?
Code example:Answer
Answer: Start a fixed number of worker loops that claim the next index and await its work. Await all workers and store results by original index.
async function mapPool(items, limit, worker) {
const out = [],
workers = [];
let i = 0;
async function run() {
while (i < items.length) {
const n = i++;
out[n] = await worker(items[n], n);
}
}
for (let n = 0; n < Math.min(limit, items.length); n++)
workers.push(run());
await Promise.all(workers);
return out;
}
74. How do you retry a failed Promise with exponential backoff?
Code example:Answer
Answer: Loop through a bounded number of attempts, return on success, and after each retryable failure await an exponentially increasing delay before rethrowing the final error.
async function retry(fn, n = 3, d = 300) {
let e;
for (let i = 0; i < n; i++) {
try {
return await fn();
} catch (x) {
e = x;
await new Promise((r) => setTimeout(r, d * 2 ** i));
}
}
throw e;
}
75. LRU cache design?
Code example:Answer
Answer: An LRU cache evicts the least recently used item when capacity is exceeded. In JavaScript, Map preserves insertion order, so get deletes and reinserts a key to mark it recent; set removes the oldest map key when over capacity. A production cache also defines TTL, memory limits, and whether undefined is a valid value.
class LRUCache {
constructor(capacity) {
this.capacity = capacity;
this.cache = new Map();
}
get(key) {
if (!this.cache.has(key)) return undefined;
const value = this.cache.get(key);
this.cache.delete(key);
this.cache.set(key, value);
return value;
}
set(key, value) {
this.cache.delete(key);
this.cache.set(key, value);
if (this.cache.size > this.capacity) {
this.cache.delete(this.cache.keys().next().value);
}
}
}
Continue practising
For output-based JavaScript practice, use the React Native JavaScript Output Practice series on Dev.to. For architecture, system design, and behavioral preparation, continue with the Complete React Native Interview Handbook 2026 series.
Top comments (0)