Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

JavaScript (ES2026) Module 4

Functions, scope and closures interview questions

Interview questions on functions, scope and closures: short warm-ups, then what each harder question tests, the first step of a good answer and its follow-ups.

24 questions: 8 warm-ups and 16 with model answers · Levels: Fresher to senior

Warm-up questions

Short questions with short answers, each answered in full.

  1. Fresher

    What is the difference between a function declaration and a function expression?

    Answered in the lesson Function declarations, expressions and return values

  2. Fresher

    When does a default parameter value apply in JavaScript?

    Answered in the lesson Parameters, defaults and rest parameters

  3. Fresher

    What is the difference between an arrow function and a regular function?

    Answered in the lesson Arrow functions

  4. Fresher

    What does lexical scope mean in JavaScript?

    Answered in the lesson Scope, the scope chain and execution contexts

  5. Fresher

    What is hoisting in JavaScript, and are let and const hoisted?

    Answered in the lesson Hoisting, var and the temporal dead zone

  6. Fresher

    What is a closure in JavaScript?

    Answered in the lesson Closures in JavaScript

  7. Fresher

    What is a higher-order function? Give two examples from JavaScript's standard library.

    Answered in the lesson Higher-order functions and callbacks

  8. Fresher

    What does the base case of a recursive function do, and what goes wrong without one?

    Answered in the lesson Recursion and the call stack

Questions with model answers

What each question tests, the first step of a good answer and the follow-ups to expect.

  1. Fresher to mid

    After an automatic reformat, getRetryPolicy() in a shared module returns undefined, and every caller silently falls back to its own hard-coded retry values. Its return statement now has the object literal on the next line. Explain what the parser does, why nothing failed loudly, and how you stop it from happening again.

    What it tests
    Automatic semicolon insertion and restricted productions, reading undefined as a symptom, and preventing the bug with a linter and tests of return values.
    First step
    Read the function the way the parser does. return may not be followed by a line break, so the statement ends there and the function returns undefined. The object literal below it is parsed as a block with a label, which is valid code that never runs.
    Follow-ups

    From the lesson Function declarations, expressions and return values

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page.

    Opening the model answers with your pass…

    Model answers open with any MySmartCoPilot pass.

    • Pro pass · 1 week₹79$2.99
    • 30 days₹179$5.99
    • 1 year₹1,699$45

    One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

    It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  2. Mid to senior

    Your error tracker groups crashes by their top stack frames, and most of the biggest groups are titled "(anonymous)". Which functions get a name automatically in JavaScript, which do not, and what would you change in the code base so that new crashes group under readable names?

    What it tests
    Function name inference, named function expressions, how names reach stack traces, and conventions and build settings that keep them.
    First step
    Find where the anonymous frames come from. Functions written directly as arguments, such as callbacks to map, then or addEventListener, get no name, while functions assigned to a variable, a property in an object literal or a default parameter take that name through name inference.
    Follow-ups

    From the lesson Function declarations, expressions and return values

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  3. Fresher to mid

    A teammate speeds up a lookup with function priceOf(sku, cache = new Map()), which checks the cache first and stores every price it fetches. In production the database still sees every single lookup. Explain why the cache never hits, where it should live instead, and how a test would have caught it.

    What it tests
    Knowing that defaults are evaluated on every call, choosing where long-lived state belongs, and testing caching with a fake data source.
    First step
    Ask when the default runs: on every call that leaves cache out. Each call builds a new, empty Map, stores one price in it and drops it when the call returns, so the next call checks a different, empty Map and goes to the database again.
    Follow-ups

    From the lesson Parameters, defaults and rest parameters

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  4. Mid to senior

    A dashboard computes Math.max(...readings) over a day of sensor readings. It worked for months, then a busy day crashed it with "RangeError: Maximum call stack size exceeded", although nothing recursive runs. Explain the mechanism, roughly where the limit is, and how you fix it and keep it fixed.

    What it tests
    Knowing that spread turns each element into an argument, that engines cap a call's arguments, and choosing code that works for any size.
    First step
    Spread passes every element as a separate argument, so a day of 150,000 readings becomes one call with 150,000 arguments. V8 places a call's arguments on its call stack, and that many do not fit, which is why the error names the stack although nothing recurses.
    Follow-ups

    From the lesson Parameters, defaults and rest parameters

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  5. Fresher to mid

    A Ticker class calls setInterval(this.tick, 1000) in start(), and tick() runs this.count += 1. In Node.js the counter stays at 0 without any error; under fake timers that pass no this, tick() throws a TypeError. Explain both, then compare three fixes: an arrow class field, bind in the constructor, and an arrow at the call site.

    What it tests
    How a method loses its this when passed as a callback, what different hosts pass as this, and the costs of the usual fixes.
    First step
    this.tick passes the function alone, without the object, and setInterval calls it later as a plain callback. Node.js passes its Timeout object as this, so the addition lands on the timer, not on the ticker; a fake timer passes undefined, and reading count from undefined throws.
    Follow-ups

    From the lesson Arrow functions

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  6. Mid to senior

    A pull request converts every function in a 2,000-line module to an arrow function "for consistency". The tests pass. As the reviewer, what can break, what gets worse even when nothing breaks, and what would you accept?

    What it tests
    Knowing everything arrows lack (this, arguments, prototype, new, hoisting, generators), judging risk beyond the tests, and setting a team convention.
    First step
    Search the diff for the features arrows do not have: this inside converted methods, arguments, functions called with new or used as prototypes, generator functions, and calls that come before the definition. Each one is a behaviour change, whatever the tests say.
    Follow-ups

    From the lesson Arrow functions

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  7. Mid to senior

    A page loads analytics.js and then app.js as classic scripts. After analytics.js is updated, app.js stops with "SyntaxError: Identifier 'config' has already been declared", and none of its lines run. Explain why, why var in both files would have hidden the problem, and how you fix it for good.

    What it tests
    The shared global scope of classic scripts, the global object against the global lexical declarations, the check before a script runs, and isolating code with modules.
    First step
    All classic scripts of a page share one global scope. The update added a top-level let or const config to analytics.js; app.js declares config at its top level too, and before running a script the engine checks its top-level declarations against the names that already exist, so app.js is refused whole.
    Follow-ups

    From the lesson Scope, the scope chain and execution contexts

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  8. Mid to senior

    In a classic browser script, var name = { first: 'Asha' }; console.log(name.first); prints undefined. The same two lines in a module, or in Node.js, print Asha. Explain the difference, and what it tells you about top-level declarations in classic scripts.

    What it tests
    How top-level var binds to properties of the global object, accessors on window, and why modules and let avoid the problem.
    First step
    Ask where the variable lives. A top-level var in a classic script is a property of the global object, and window already has a name property, an accessor that stores the window's name as a string. The declaration reuses that property, so the assignment calls its setter and stores "[object Object]".
    Follow-ups

    From the lesson Scope, the scope chain and execution contexts

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  9. Mid to senior

    A teammate replaced every var with let in a 600-line legacy checkout script. All tests pass, but in production a rarely used path now throws a ReferenceError. How do you find every place like it before the next release, and what do you put in place so that it cannot happen again?

    What it tests
    What var allowed that let does not, telling the two kinds of ReferenceError apart, finding them with lint rules and coverage, and converting safely.
    First step
    Ask what var allowed that let does not: a name used outside the block that declares it, or read above its declaration. Both now throw, but only on the path that reaches them, which is why the tests stayed green. The error message tells you which kind you have; then let the linter list the others instead of reading 600 lines.
    Follow-ups

    From the lesson Hoisting, var and the temporal dead zone

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  10. Mid to senior

    config.mjs imports defaults from rules.mjs, and rules.mjs imports region from config.mjs to build those defaults. Starting the app with config.mjs fails with "ReferenceError: Cannot access 'region' before initialization". Explain the order in which the two modules run, why an exported function would have survived, and how you fix it.

    What it tests
    How ES modules are linked and then run, import cycles, the temporal dead zone across modules, and restructuring shared values.
    First step
    Work out which module runs first. The entry, config.mjs, imports rules.mjs, so rules.mjs runs before it, even though rules.mjs imports config.mjs too: that module is already in progress. rules.mjs reads region at its top level while the const line of config.mjs has not run, so region is still in its temporal dead zone.
    Follow-ups

    From the lesson Hoisting, var and the temporal dead zone

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  11. Mid to senior

    A dashboard's memory grows by about 40 MB an hour. After a working day, a heap snapshot shows over a hundred 2 MB report arrays, kept alive through the contexts of small click handlers that only read a report's title. Explain how the closures keep them alive, how you would fix it and how you would prove the fix.

    What it tests
    What a closure keeps alive, registered listeners as roots, contexts shared by the closures of one call, removing listeners and capturing less, and proving a leak fix.
    First step
    Ask what holds the handlers. A registered listener stays alive until it is removed, and each handler keeps the environment of the call that made it. Check whether the panel adds new listeners on every render without removing the old ones, and which variables of that render call its handlers share.
    Follow-ups

    From the lesson Closures in JavaScript

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  12. Mid to senior

    Write once() for an SDK's asynchronous init(), which 20 parts of a page await during start-up. What should a caller get while the first call is still running, and after it has failed? Walk through the edge cases you would decide on and test.

    What it tests
    Caching a promise rather than a result, concurrent callers, retrying after a failure, synchronous throws, this and arguments, and testing with a controllable fake.
    First step
    Decide what is remembered. Caching the result only once the work has finished lets every caller that arrives in between start its own request, so cache the promise itself: the first call creates it, and every later call returns that same promise, settled or not.
    Follow-ups

    From the lesson Closures in JavaScript

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 2 minutes
  13. Mid to senior

    An import runs 50,000 rows through pipe(parseRow, validate, enrich, save). One malformed row throws inside enrich, and the import stops after 12,000 rows with nothing reported for the rest. How would you change the pipeline so that bad rows are reported and skipped, and what do you trade off?

    What it tests
    Error handling in function pipelines, wrapping steps with higher-order helpers, reporting rejected rows, failure thresholds and saves that are safe to repeat.
    First step
    Find where the error escapes. A step that throws ends the pipeline's call, and nothing catches it per row, so the loop stops with it. Decide what a failed row should mean, then catch errors around each row's pipeline, record the row number and the step, and go on with the next row.
    Follow-ups

    From the lesson Higher-order functions and callbacks

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  14. Mid to senior

    getRate(code, callback) calls back at once when the rate is cached and after a network request otherwise. Checkout code that sets a variable after calling getRate() works in every test, but in production most requests show a wrong total or a ReferenceError. Explain why, and how you would redesign getRate().

    What it tests
    When callbacks run, functions that call back sometimes at once and sometimes later, why tests miss it, and deferring callbacks or returning promises.
    First step
    Compare the two paths. On a cache miss the callback runs after the checkout code has finished; on a hit it runs inside getRate(), before the caller's next line has run. Tests start with an empty cache, so they only ever take the miss path.
    Follow-ups

    From the lesson Higher-order functions and callbacks

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  15. Mid to senior

    A service validates partner JSON with a recursive walk. A partner starts sending a 2 MB document nested 30,000 levels deep, and every request now fails with RangeError: Maximum call stack size exceeded. What do you change, and how do you protect the service from such input in general?

    What it tests
    Call stack limits, which parts of the platform recurse, rewriting a walk with an explicit stack, and depth and size limits on input.
    First step
    Find the code that overflows. Each level of the document costs at least one frame in a recursive walk, and an engine allows only a few thousand, so 30,000 levels cannot work. Check the service's own walk first, then recursive helpers that run on the same document, such as JSON.stringify in the error log.
    Follow-ups

    From the lesson Recursion and the call stack

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  16. Mid to senior

    A nightly job walks 2 million folders recursively, and the deepest path has 40 levels. A teammate wants to rewrite it with an explicit stack so that it can never crash. Is the rewrite worth it? Say what you would check first, and when you would insist on it.

    What it tests
    Depth against size, the measured stack limit, cycles from links, the memory an explicit stack needs, and when recursion is the better code.
    First step
    Separate size from depth. Two million folders means two million calls in all, but only the calls on the current path wait on the stack at the same time, about 40 here. Compare that with the few thousand frames a JavaScript engine allows.
    Follow-ups

    From the lesson Recursion and the call stack

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes

All JavaScript (ES2026) interview questions · The JavaScript (ES2026) track

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.