JavaScript Output Based Questions, with Answers

50 "what does this code print?" questions of the kind interviewers use to test the event loop, closures, this, hoisting and coercion. Read the code, write down the output, then open the answer.

They run from Easy to Hard. Each one links to a lesson that traces the code line by line, so a wrong guess shows you exactly where your model of JavaScript went off. More questions by level: for freshers and for experienced developers.

  1. 01 · JavaScript Fundamentals for Frontend Interviews · Easy

    Primitive vs Reference Types

    What is printed to the console when the following JavaScript code executes, and why does mutating a property behave differently than reassigning the parameter?

    let primitiveVal = 42;
    let objA = { count: 1 };
    let objB = objA;
    
    function update(num, target) {
      num = 100;
      target.count = 5;
      target = { count: 999 };
    }
    
    update(primitiveVal, objA);
    
    console.log(primitiveVal, objA.count, objB.count);
    Show the output
    42 5 5
    Why it prints this, traced line by line
  2. 02 · JavaScript Fundamentals for Frontend Interviews · Medium

    Type Coercion & Equality

    What is the exact output printed to the console when evaluating the following statements in standard ECMAScript?

    const res1 = 1 + '2' + 3;
    const res2 = 4 - '2' + '1';
    const res3 = [] == ![];
    const res4 = [1, 2] + [3, 4];
    
    console.log(res1, res2, res3, res4);
    Show the output
    '123' '21' true '1,23,4'
    Why it prints this, traced line by line
  3. 03 · JavaScript Fundamentals for Frontend Interviews · Medium

    Scope, Hoisting & TDZ

    What is printed to the console when the following snippet executes, and why does bar() behave differently than foo()?

    console.log(typeof nonExistent); 
    console.log(typeof hoistedVar);
    
    var hoistedVar = 10;
    
    function testScope() {
      console.log(hoistedVar);
      var hoistedVar = 20;
      console.log(hoistedVar);
    }
    
    testScope();
    Show the output
    'undefined' 'undefined' undefined 20
    Why it prints this, traced line by line
  4. 04 · JavaScript Fundamentals for Frontend Interviews · Medium

    Objects, Arrays & Reference Semantics

    What is logged to the console when the following code executes, and how do object aliasing and shallow copying affect nested property mutation?

    const original = {
      id: 1,
      tags: ['js', 'web'],
      meta: { views: 100 },
    };
    
    const shallowCopy = { ...original };
    const alias = original;
    
    shallowCopy.id = 2;
    shallowCopy.tags.push('v8');
    shallowCopy.meta.views += 50;
    
    alias.id = 3;
    
    const res1 = original.id;
    const res2 = original.tags.length;
    const res3 = original.meta.views;
    const res4 = original === shallowCopy;
    const res5 = original.meta === shallowCopy.meta;
    
    console.log(res1, res2, res3, res4, res5);
    Show the output
    3 3 150 false true
    Why it prints this, traced line by line
  5. 05 · JavaScript Fundamentals for Frontend Interviews · Medium

    Equality, Coercion & Comparison Traps

    What is logged to the console when the following equality and relational comparisons execute, and why do loose equality and relational operators handle null and arrays with fundamentally different rules?

    const c1 = null >= 0;
    const c2 = null == 0;
    const c3 = '12' < '9';
    const c4 = Object.is(NaN, NaN);
    const c5 = Object.is(+0, -0);
    const c6 = [0] == false;
    
    console.log(c1, c2, c3, c4, c5, c6);
    Show the output
    true false true true false true
    Why it prints this, traced line by line
  6. 06 · Execution Contexts, Closures, and Object Prototypes · Medium

    Execution Context & Call Stack

    What is the exact logged output when the following JavaScript code executes, and how does the V8 call stack transition through each function invocation and return?

    function first() {
      console.log('first:start');
      second();
      console.log('first:end');
    }
    
    function second() {
      console.log('second:start');
      third();
      console.log('second:end');
    }
    
    function third() {
      console.log('third:exec');
    }
    
    first();
    Show the output
    first:start second:start third:exec second:end first:end
    Why it prints this, traced line by line
  7. 07 · Execution Contexts, Closures, and Object Prototypes · Medium

    Closures & Lexical Scope

    What is printed to the console when the following timer function executes, and how does JavaScript closure scoping determine the printed numbers?

    function runTimers() {
      for (var i = 0; i < 3; i++) {
        setTimeout(function() {
          console.log('var:', i);
        }, 10);
      }
    
      for (let j = 0; j < 3; j++) {
        setTimeout(function() {
          console.log('let:', j);
        }, 10);
      }
    }
    
    runTimers();
    Show the output
    var: 3 (x3), let: 0, 1, 2
    Why it prints this, traced line by line
  8. 08 · Execution Contexts, Closures, and Object Prototypes · Medium

    this, call, apply & bind

    What is printed to the console when the following JavaScript code executes, and how do explicit binding and arrow functions alter the value of 'this'?

    const obj = {
      name: 'Alice',
      regular() {
        return this.name;
      },
      getArrow() {
        return () => this.name;
      },
    };
    
    const bob = { name: 'Bob' };
    const charlie = { name: 'Charlie' };
    
    const extracted = obj.regular;
    const bound = obj.regular.bind(bob);
    const nestedArrow = obj.getArrow();
    
    console.log(
      obj.regular(),
      extracted.call(charlie),
      bound.call(charlie),
      nestedArrow.call(charlie)
    );
    Show the output
    Alice Charlie Bob Alice
    Why it prints this, traced line by line
  9. 09 · Execution Contexts, Closures, and Object Prototypes · Medium

    Prototypes & Inheritance

    What is logged to the console when the following code executes, and how does property deletion interact with shadowed prototype properties?

    function Device(brand) {
      this.brand = brand;
    }
    
    Device.prototype.category = 'electronics';
    Device.prototype.battery = 100;
    
    const phone = new Device('Acme');
    
    phone.battery = 85;
    
    const res1 = phone.battery;
    delete phone.battery;
    const res2 = phone.battery;
    delete phone.category;
    const res3 = phone.category;
    const res4 = phone.hasOwnProperty('battery');
    const res5 = 'battery' in phone;
    
    console.log(res1, res2, res3, res4, res5);
    Show the output
    85 100 electronics false true
    Why it prints this, traced line by line
  10. 10 · Execution Contexts, Closures, and Object Prototypes · Medium

    Property Flags & Descriptors

    What is logged to the console when the following code executes, and how do Object.defineProperty descriptor defaults affect enumeration, mutation, and deletion?

    const obj = {};
    
    Object.defineProperty(obj, 'id', {
      value: 101,
      // writable, enumerable, configurable omitted
    });
    
    obj.title = 'Widget';
    
    const keys = Object.keys(obj);
    
    obj.id = 999;
    
    const deleteId = delete obj.id;
    
    const ownNames = Object.getOwnPropertyNames(obj);
    
    console.log(keys.join(','), obj.id, deleteId, ownNames.join(','));
    Show the output
    title 101 false id,title
    Why it prints this, traced line by line
  11. 11 · The Event Loop, Microtasks, and Asynchronous Concurrency · Medium

    Promises & Chaining

    What output is logged to the console when the following promise chain executes, and how do errors propagate through .catch() and .finally()?

    const results = [];
    
    Promise.resolve('start')
      .then((val) => {
        results.push(val);
        throw new Error('fail');
      })
      .then(() => {
        results.push('unreachable');
      })
      .catch((err) => {
        results.push('caught: ' + err.message);
        return 'recovered';
      })
      .finally(() => {
        results.push('cleanup');
        return 'ignored';
      })
      .then((val) => {
        results.push('end: ' + val);
        console.log(results.join(' -> '));
      });
    Show the output
    start -> caught: fail -> cleanup -> end: recovered
    Why it prints this, traced line by line
  12. 12 · The Event Loop, Microtasks, and Asynchronous Concurrency · Medium

    async/await Internals

    What is the exact sequence of outputs printed to the console when the following JavaScript code executes, and how do async/await suspension cycles interleave with Promise.then() microtasks?

    async function main() {
      console.log('1');
      await null;
      console.log('2');
      await Promise.resolve();
      console.log('3');
    }
    
    console.log('A');
    main();
    console.log('B');
    
    Promise.resolve()
      .then(() => {
        console.log('C');
      })
      .then(() => {
        console.log('D');
      });
    
    console.log('E');
    Show the output
    A 1 B E 2 C 3 D
    Why it prints this, traced line by line
  13. 13 · The Event Loop, Microtasks, and Asynchronous Concurrency · Medium

    Promise Combinators (all, allSettled, race, any)

    What is logged to the console when the four Promise combinators execute with a rejected and a resolved promise, and how do their fulfillment and rejection rules diverge?

    async function runCombinators() {
      const p1 = Promise.reject('E1');
      const p2 = Promise.resolve('OK');
    
      const res1 = await Promise.all([p1, p2]).catch((e) => `all:${e}`);
      const res2 = await Promise.any([p1, p2]).then((v) => `any:${v}`);
      const res3 = await Promise.race([p1, p2]).catch((e) => `race:${e}`);
      const res4 = await Promise.allSettled([p1, p2]).then((s) =>
        `settled:${s.map((x) => x.status).join(',')}`
      );
    
      console.log([res1, res2, res3, res4].join(' '));
    }
    
    runCombinators();
    Show the output
    all:E1 any:OK race:E1 settled:rejected,fulfilled
    Why it prints this, traced line by line
  14. 14 · The Event Loop, Microtasks, and Asynchronous Concurrency · Medium

    Timers & Concurrency Control

    What is logged to the console when the following timer and microtask scheduling code executes, and how does the event loop interleave microtasks created inside a macrotask callback before processing subsequent macrotasks?

    const order = [];
    
    order.push('sync-1');
    
    setTimeout(() => {
      order.push('timer-1');
      Promise.resolve().then(() => order.push('micro-after-t1'));
    }, 0);
    
    setTimeout(() => {
      order.push('timer-2');
      console.log(order.join(' '));
    }, 0);
    
    Promise.resolve().then(() => {
      order.push('micro-1');
      queueMicrotask(() => order.push('micro-2'));
    });
    
    order.push('sync-2');
    Show the output
    sync-1 sync-2 micro-1 micro-2 timer-1 micro-after-t1 timer-2
    Why it prints this, traced line by line
  15. 15 · Tricky JavaScript Output Prediction & Code Reasoning · Medium

    Hoisting & Scope Traps

    What is logged to the console when the following functions execute, and how do parameter scoping, function declaration precedence, and loop variable hoisting resolve?

    var x = 10;
    
    function parameterScope(a = x) {
      var x = 20;
      return a;
    }
    
    function declarationPrecedence() {
      var before = typeof entity;
      function entity() {}
      var entity = 'reassigned';
      return before + ' ' + typeof entity;
    }
    
    var b = 1;
    for (var b = 0; b < 3; b++) {}
    
    console.log(parameterScope(), declarationPrecedence(), b);
    Show the output
    10 function string 3
    Why it prints this, traced line by line
  16. 16 · JavaScript Utility Implementations and Standard Polyfills · Medium

    Debounce and Throttle Implementations

    What is logged to the console when the following code executes, and how do debounce cancellation and leading-edge throttling alter callback dispatch order?

    function debounce(fn, delay) {
      let timerId = null;
      return function (...args) {
        if (timerId) clearTimeout(timerId);
        timerId = setTimeout(() => {
          fn.apply(this, args);
          timerId = null;
        }, delay);
      };
    }
    
    function throttle(fn, limit) {
      let inThrottle = false;
      return function (...args) {
        if (!inThrottle) {
          fn.apply(this, args);
          inThrottle = true;
          setTimeout(() => {
            inThrottle = false;
          }, limit);
        }
      };
    }
    
    const logs = [];
    const logPush = (msg) => logs.push(msg);
    
    const debounced = debounce((v) => logPush(`deb:${v}`), 50);
    const throttled = throttle((v) => logPush(`thr:${v}`), 50);
    
    throttled('1');
    throttled('2');
    debounced('A');
    debounced('B');
    logPush('sync-end');
    
    setTimeout(() => {
      console.log(logs.join(' '));
    }, 100);
    Show the output
    thr:1 sync-end deb:B
    Why it prints this, traced line by line
  17. 17 · JavaScript Utility Implementations and Standard Polyfills · Medium

    Flattening Nested Arrays

    What is logged to the console when Array.prototype.flat() is executed on deeply nested and sparse arrays, and how does the native flattening algorithm handle uninitialized empty slots?

    const nested = [1, [2, [3, [4]]]];
    const res1 = nested.flat(1);
    const res2 = nested.flat(Infinity);
    
    const sparse = [1, , 3];
    const res3 = sparse.flat();
    
    console.log(
      res1.length,
      res2.join('-'),
      res3.length,
      1 in sparse
    );
    Show the output
    3 1-2-3-4 2 false
    Why it prints this, traced line by line
  18. 18 · JavaScript Utility Implementations and Standard Polyfills · Medium

    Higher-Order Functions & Currying

    What is logged to the console when the following code executes, and how does the execution order differ between pipe() and compose()?

    const add = (a) => (b) => a + b;
    const multiply = (a) => (b) => a * b;
    
    const addFive = add(5);
    const double = multiply(2);
    
    const pipe = (...fns) => (x) => fns.reduce((v, f) => f(v), x);
    const compose = (...fns) => (x) => fns.reduceRight((v, f) => f(v), x);
    
    const pipeline = pipe(addFive, double);
    const composed = compose(addFive, double);
    
    const res1 = add(3)(4);
    const res2 = pipeline(10);
    const res3 = composed(10);
    
    console.log(res1, res2, res3);
    Show the output
    7 30 25
    Why it prints this, traced line by line
  19. 19 · JavaScript Utility Implementations and Standard Polyfills · Medium

    JavaScript Array Methods

    What is logged to the console when the following JavaScript code executes, and how do missing return statements and method return values affect the outcome?

    const nums = [1, 2, 3, 4];
    
    const mapped = nums.map((n) => {
      if (n % 2 === 0) return n * 2;
    });
    
    const filtered = nums.filter((n) => {
      n > 1;
    });
    
    const reduced = [1, 2, 3].reduce((acc, curr) => acc + curr, 10);
    
    const list = [1, 2];
    const forEachRet = list.forEach((n, i, arr) => {
      arr[i] = n * 10;
    });
    
    console.log(
      mapped.join(','),
      filtered.length,
      reduced,
      String(forEachRet),
      list.join(',')
    );
    Show the output
    ,4,,8 0 16 undefined 10,20
    Why it prints this, traced line by line
  20. 20 · Browser APIs, DOM Performance, and Client-Side Security · Medium

    DOM Traversal & Reflow

    What is logged to the console when the following DOM element and fragment manipulation operations execute, and how do childNodes versus children and DocumentFragment insertions affect tree structure?

    const parent = document.createElement('div');
    parent.innerHTML = '<span>A</span><!-- comment --><p>B</p>';
    
    const childNodesCount = parent.childNodes.length;
    const childrenCount = parent.children.length;
    
    const span = parent.children[0];
    const closestDiv = span.closest('div') === parent;
    
    const fragment = document.createDocumentFragment();
    fragment.appendChild(document.createElement('section'));
    parent.appendChild(fragment);
    
    const finalChildren = parent.children.length;
    
    console.log(childNodesCount, childrenCount, closestDiv, finalChildren);
    Show the output
    3 2 true 3
    Why it prints this, traced line by line
  21. 21 · Browser APIs, DOM Performance, and Client-Side Security · Medium

    Web Storage, Cookies & Persistence

    What is logged to the console when the following Web Storage operations execute, and how do implicit string coercion and serialization dictate stored types?

    class StorageMock {
      constructor() {
        this.store = new Map();
      }
      setItem(k, v) {
        this.store.set(String(k), String(v));
      }
      getItem(k) {
        const val = this.store.get(String(k));
        return val !== undefined ? val : null;
      }
    }
    
    const storage = new StorageMock();
    
    // 1. Storing object without serialization
    storage.setItem('user', { id: 1 });
    const rawUser = storage.getItem('user');
    
    // 2. Storing number and boolean
    storage.setItem('count', 42);
    storage.setItem('active', false);
    const countType = typeof storage.getItem('count');
    const activeVal = storage.getItem('active');
    
    // 3. Proper JSON serialization
    storage.setItem('session', JSON.stringify({ token: 'xyz' }));
    const parsedToken = JSON.parse(storage.getItem('session')).token;
    
    console.log(rawUser, countType, activeVal, parsedToken);
    Show the output
    [object Object] string false xyz
    Why it prints this, traced line by line
  22. 22 · Modern JavaScript: ES Modules, Iterators, and Weak Collections · Medium

    JavaScript Modules (ESM vs CommonJS)

    What is printed to the console when the following code executes, and how does the live binding model of ES Modules contrast with CommonJS value exports?

    const esmExport = (() => {
      let counter = 10;
      return {
        get counter() {
          return counter;
        },
        increment() {
          counter += 5;
        },
      };
    })();
    
    const cjsExport = (() => {
      let counter = 10;
      return {
        counter,
        increment() {
          counter += 5;
        },
      };
    })();
    
    const beforeESM = esmExport.counter;
    const beforeCJS = cjsExport.counter;
    
    esmExport.increment();
    cjsExport.increment();
    
    const afterESM = esmExport.counter;
    const afterCJS = cjsExport.counter;
    
    console.log(beforeESM, beforeCJS, afterESM, afterCJS);
    Show the output
    10 10 15 10
    Why it prints this, traced line by line
  23. 23 · Modern JavaScript: ES Modules, Iterators, and Weak Collections · Medium

    Iterators & Generators

    What is logged to the console when the generator is driven step-by-step with next(), and how do yield argument injection and iterator exhaustion operate?

    function* stepSequence(start) {
      const step1 = yield start * 2;
      const step2 = yield (step1 || 1) + 10;
      return 'DONE';
    }
    
    const gen = stepSequence(5);
    
    const v1 = gen.next().value;
    const v2 = gen.next(20).value;
    const r3 = gen.next();
    const v3 = r3.value;
    const v4 = gen.next().value;
    
    console.log(v1, v2, v3, String(v4));
    Show the output
    10 30 DONE undefined
    Why it prints this, traced line by line
  24. 24 · Modern JavaScript: ES Modules, Iterators, and Weak Collections · Medium

    Maps, Sets, WeakMap & WeakSet

    What is logged to the console when the following Map and Set operations execute, and how do object reference identity and SameValueZero equality determine collection size and retrieval?

    const map = new Map();
    const set = new Set();
    
    const keyObj = { id: 1 };
    map.set(keyObj, 'original');
    map.set({ id: 1 }, 'duplicate?');
    map.set(NaN, 'first-nan');
    map.set(NaN, 'second-nan');
    
    set.add(keyObj);
    set.add({ id: 1 });
    set.add(NaN);
    set.add(NaN);
    
    const res1 = map.size;
    const res2 = set.size;
    const res3 = map.get(keyObj);
    const res4 = map.get({ id: 1 });
    
    console.log(res1, res2, res3, String(res4));
    Show the output
    3 3 original undefined
    Why it prints this, traced line by line
  25. 25 · Modern JavaScript: ES Modules, Iterators, and Weak Collections · Medium

    JavaScript Classes & Inheritance

    What is logged to the console when the following class hierarchy executes, and how do static inheritance, private fields, and prototype enumerability operate?

    class Vehicle {
      #fuel = 100;
      static count = 0;
    
      constructor(brand) {
        this.brand = brand;
        Vehicle.count++;
      }
    
      getFuel() {
        return this.#fuel;
      }
    
      static getCount() {
        return this.count;
      }
    }
    
    class Car extends Vehicle {
      constructor(brand, doors = 4) {
        super(brand);
        this.doors = doors;
      }
    
      getDetails() {
        return this.brand + '-' + this.doors + '-' + this.getFuel();
      }
    }
    
    const c1 = new Car('Tesla', 2);
    const res1 = c1.getDetails();
    const res2 = Car.getCount();
    const res3 = Object.keys(Car.prototype).length;
    const res4 = c1 instanceof Vehicle;
    
    console.log(res1, res2, res3, res4);
    Show the output
    Tesla-2-100 1 0 true
    Why it prints this, traced line by line
  26. 26 · Modern JavaScript: ES Modules, Iterators, and Weak Collections · Medium

    Tagged Templates & Frontend Security

    What is logged to the console when the following safeHtml tagged template function processes an untrusted user payload and a role string containing special characters?

    function escapeHtml(str) {
      return String(str)
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#39;');
    }
    
    function safeHtml(strings, ...values) {
      return strings.reduce((acc, str, i) => {
        const val = i < values.length ? escapeHtml(values[i]) : '';
        return acc + str + val;
      }, '');
    }
    
    const user = '<img src=x onerror=alert(1)>';
    const role = 'Admin & Lead';
    
    const safe = safeHtml`<span>User: ${user} (${role})</span>`;
    
    const hasRawTag = safe.includes('<img');
    const hasEscapedTag = safe.includes('&lt;img');
    const hasEscapedAmp = safe.includes('&amp;');
    
    console.log(hasRawTag, hasEscapedTag, hasEscapedAmp);
    Show the output
    false true true
    Why it prints this, traced line by line
  27. 27 · Debugging, Memory Leak Analysis, and Code Quality · Medium

    Error Handling & Debugging

    What is logged to the console when the following code executes, and why does returning inside a finally block override previous return statements?

    function processData(val) {
      try {
        if (val < 0) {
          throw new RangeError('Must be positive');
        }
        return val * 2;
      } catch (err) {
        if (err instanceof RangeError) {
          return 'handled-range';
        }
        throw err;
      }
    }
    
    function computeWithFinally() {
      try {
        throw new Error('fail');
      } catch (err) {
        return 'from-catch';
      } finally {
        return 'from-finally';
      }
    }
    
    const res1 = processData(5);
    const res2 = processData(-1);
    const res3 = computeWithFinally();
    
    console.log(res1, res2, res3);
    Show the output
    10 handled-range from-finally
    Why it prints this, traced line by line
  28. 28 · JavaScript Fundamentals for Frontend Interviews · Hard

    Memory Management & Garbage Collection

    What is logged to the console when the following object reference graph is mutated, and why do circular references remain reachable as long as an active path from a root exists?

    let parent = { name: 'parent' };
    let child = { name: 'child' };
    
    // 1. Establish circular references
    parent.child = child;
    child.parent = parent;
    
    // 2. Break root reference to parent
    const childRef = parent.child;
    parent = null;
    
    // 3. Inspect reachability through childRef
    const res1 = childRef.name;
    const res2 = childRef.parent ? childRef.parent.name : null;
    const res3 = childRef.parent.child === childRef;
    
    console.log(res1, res2, res3);
    Show the output
    child parent true
    Why it prints this, traced line by line
  29. 29 · The Event Loop, Microtasks, and Asynchronous Concurrency · Hard

    Event Loop & Microtasks

    What is the exact order of numbers printed to the console when the following JavaScript snippet executes?

    console.log(1);
    
    setTimeout(() => {
      console.log(2);
    }, 0);
    
    Promise.resolve()
      .then(() => {
        console.log(3);
        return Promise.resolve(4);
      })
      .then((val) => {
        console.log(val);
      });
    
    queueMicrotask(() => {
      console.log(5);
    });
    
    console.log(6);
    Show the output
    1 6 3 5 4 2
    Why it prints this, traced line by line
  30. 30 · The Event Loop, Microtasks, and Asynchronous Concurrency · Hard

    Promise Concurrency Pool

    What is logged to the console when the following promisePool utility executes four tasks with variable delays under a concurrency limit of 2?

    async function promisePool(tasks, limit) {
      const results = [];
      const executing = new Set();
      let peak = 0;
    
      for (const [index, task] of tasks.entries()) {
        const p = Promise.resolve().then(task).then((res) => {
          results[index] = res;
          executing.delete(p);
        });
        executing.add(p);
        peak = Math.max(peak, executing.size);
        if (executing.size >= limit) {
          await Promise.race(executing);
        }
      }
      await Promise.all(executing);
      return { results, peak };
    }
    
    async function run() {
      const logs = [];
      const delayTask = (id, ms) => () =>
        new Promise((resolve) =>
          setTimeout(() => {
            logs.push('done:' + id);
            resolve(id * 10);
          }, ms)
        );
    
      const tasks = [
        delayTask(1, 30),
        delayTask(2, 10),
        delayTask(3, 20),
        delayTask(4, 10)
      ];
    
      const { results, peak } = await promisePool(tasks, 2);
      console.log(logs.join(' ') + ' | peak:' + peak + ' | res:' + results.join(','));
    }
    
    run();
    Show the output
    done:2 done:1 done:3 done:4 | peak:2 | res:10,20,30,40
    Why it prints this, traced line by line
  31. 31 · The Event Loop, Microtasks, and Asynchronous Concurrency · Hard

    Async Iterators & Streaming Backpressure

    What is logged to the console when the following async generator pipeline is consumed with for await...of and terminated early via a break statement?

    let cleanedUp = false;
    
    async function* generateChunks(count) {
      try {
        for (let i = 1; i <= count; i++) {
          yield Promise.resolve(i * 10);
        }
      } finally {
        cleanedUp = true;
      }
    }
    
    async function processStream() {
      const received = [];
      for await (const chunk of generateChunks(5)) {
        received.push(chunk);
        if (chunk === 30) {
          break;
        }
      }
      return { received, cleanedUp };
    }
    
    processStream().then(({ received, cleanedUp }) => {
      console.log(received.join(','), cleanedUp);
    });
    Show the output
    10,20,30 true
    Why it prints this, traced line by line
  32. 32 · Tricky JavaScript Output Prediction & Code Reasoning · Hard

    this Context Traps

    What is logged to the console when the following object methods, arrow functions, and bound functions are invoked, and why does chained binding preserve the original target context?

    const user = { 
      id: 'master',
      getId() {
        return this.id;
      },
      getNested() {
        const inner = () => this.id;
        return inner();
      }
    };
    
    const boundA = user.getId.bind({ id: 'worker' });
    const boundB = boundA.bind({ id: 'guest' });
    
    const res1 = user.getId();
    const res2 = user.getNested();
    const res3 = boundB();
    const res4 = boundA.call({ id: 'admin' });
    
    console.log(res1, res2, res3, res4);
    Show the output
    master master worker worker
    Why it prints this, traced line by line
  33. 33 · Tricky JavaScript Output Prediction & Code Reasoning · Hard

    Async Execution Ordering

    What is logged to the console when the following code executes, and how do async/await expressions interleave with chained Promise.then callbacks and timer macrotasks?

    const log = [];
    
    log.push('1');
    
    setTimeout(() => {
      log.push('2');
      console.log(log.join(' '));
    }, 0);
    
    async function asyncFn() {
      log.push('3');
      await null;
      log.push('4');
    }
    
    asyncFn();
    
    new Promise((resolve) => {
      log.push('5');
      resolve();
    })
      .then(() => {
        log.push('6');
      })
      .then(() => {
        log.push('7');
      });
    
    log.push('8');
    Show the output
    1 3 5 8 4 6 7 2
    Why it prints this, traced line by line
  34. 34 · Tricky JavaScript Output Prediction & Code Reasoning · Hard

    Coercion & Mutation Traps

    What is logged to the console when the following object property indexing, array parameter mutation, and primitive coercion expressions execute?

    const a = {};
    const b = { key: 'b' };
    const c = { key: 'c' };
    
    a[b] = 123;
    a[c] = 456;
    
    const arr = [1, 2, 3];
    function mutate(list, item) {
      list.push(item);
      list = [99];
      list.push(100);
    }
    mutate(arr, 4);
    
    const res1 = a[b];
    const res2 = arr.length;
    const res3 = [] + {};
    const res4 = (null == undefined) + '-' + (null === undefined);
    
    console.log(res1, res2, res3, res4);
    Show the output
    456 4 [object Object] true-false
    Why it prints this, traced line by line
  35. 35 · JavaScript Utility Implementations and Standard Polyfills · Hard

    Memoize and Cache Layer

    What is logged to the console when the following memoized functions are invoked, and how do default JSON argument serialization versus custom key resolvers determine cache hit rates?

    function memoize(fn, resolver) {
      const cache = new Map();
      return function (...args) {
        const key = resolver ? resolver(...args) : JSON.stringify(args);
        if (cache.has(key)) {
          return { value: cache.get(key), cached: true };
        }
        const result = fn.apply(this, args);
        cache.set(key, result);
        return { value: result, cached: false };
      };
    }
    
    let calls = 0;
    const add = (a, b) => {
      calls++;
      return a + b;
    };
    
    const defaultMem = memoize(add);
    const customMem = memoize(add, (a, b) => [a, b].sort().join(','));
    
    const r1 = defaultMem(1, 2);
    const r2 = defaultMem(1, 2);
    const r3 = defaultMem(2, 1);
    const r4 = customMem(1, 2);
    const r5 = customMem(2, 1);
    
    console.log(calls, r1.cached, r2.cached, r3.cached, r5.cached);
    Show the output
    3 false true false true
    Why it prints this, traced line by line
  36. 36 · JavaScript Utility Implementations and Standard Polyfills · Hard

    Retry with Exponential Backoff & Jitter

    What is logged to the console when the following retry utility executes against an API that fails twice with 503 errors before succeeding, using an injected deterministic sleep provider?

    async function retryWithBackoff(fn, options = {}) {
      const { maxRetries = 3, baseDelay = 100, shouldRetry = () => true, sleep = (ms) => new Promise(r => setTimeout(r, ms)) } = options;
      let attempt = 0;
      while (true) {
        try {
          return await fn(attempt);
        } catch (err) {
          attempt++;
          if (attempt > maxRetries || !shouldRetry(err)) {
            throw err;
          }
          const delay = baseDelay * (2 ** (attempt - 1));
          await sleep(delay);
        }
      }
    }
    
    const delays = [];
    const mockSleep = (ms) => { delays.push(ms); return Promise.resolve(); };
    
    let callCount = 0;
    const flakeyApi = async (attempt) => {
      callCount++;
      if (callCount < 3) {
        const err = new Error('503 Service Unavailable');
        err.status = 503;
        throw err;
      }
      return 'SUCCESS';
    };
    
    const isRetryable = (err) => err.status >= 500;
    
    retryWithBackoff(flakeyApi, { maxRetries: 3, baseDelay: 50, shouldRetry: isRetryable, sleep: mockSleep })
      .then((result) => {
        console.log(result, callCount, delays.join(','));
      });
    Show the output
    SUCCESS 3 50,100
    Why it prints this, traced line by line
  37. 37 · Browser APIs, DOM Performance, and Client-Side Security · Hard

    IntersectionObserver & List Virtualization

    What is logged to the console when the following framework-independent list virtualization window calculation executes for a dataset of 1,000 items with overscan buffering?

    function computeVirtualWindow({ total, itemHeight, viewportHeight, scrollTop, overscan = 1 }) {
      if (total === 0) return { totalHeight: 0, startIndex: 0, endIndex: -1, visibleCount: 0, offsetY: 0 };
      const totalHeight = total * itemHeight;
      const rawStart = Math.floor(scrollTop / itemHeight);
      const visibleCapacity = Math.ceil(viewportHeight / itemHeight);
      const rawEnd = rawStart + visibleCapacity - 1;
    
      const startIndex = Math.max(0, rawStart - overscan);
      const endIndex = Math.min(total - 1, rawEnd + overscan);
      const visibleCount = endIndex >= startIndex ? endIndex - startIndex + 1 : 0;
      const offsetY = startIndex * itemHeight;
    
      return { totalHeight, startIndex, endIndex, visibleCount, offsetY };
    }
    
    const win = computeVirtualWindow({
      total: 1000,
      itemHeight: 40,
      viewportHeight: 200,
      scrollTop: 120,
      overscan: 1,
    });
    
    console.log(win.totalHeight, win.startIndex, win.endIndex, win.visibleCount, win.offsetY);
    Show the output
    40000 2 8 7 80
    Why it prints this, traced line by line
  38. 38 · Browser APIs, DOM Performance, and Client-Side Security · Hard

    Web Workers & Transferable Objects

    What is logged to the console when the following snippet demonstrates structured cloning versus zero-copy memory ownership transfer with ArrayBuffers, and why does the source buffer become detached?

    const regularObj = { data: [1, 2, 3] };
    const clonedObj = structuredClone(regularObj);
    clonedObj.data.push(4);
    
    const sourceBuffer = new ArrayBuffer(16);
    const viewBefore = new Uint8Array(sourceBuffer);
    viewBefore[0] = 99;
    
    const transferPayload = structuredClone(
      { payload: sourceBuffer },
      { transfer: [sourceBuffer] }
    );
    
    const isDetached = sourceBuffer.byteLength === 0;
    const destLength = transferPayload.payload.byteLength;
    const destVal = new Uint8Array(transferPayload.payload)[0];
    
    console.log(regularObj.data.length, clonedObj.data.length, isDetached, destLength, destVal);
    Show the output
    3 4 true 16 99
    Why it prints this, traced line by line
  39. 39 · Modern JavaScript: ES Modules, Iterators, and Weak Collections · Hard

    Symbols & Metaprogramming

    What is logged to the console when local vs global symbols are compared, an object with a symbol key and Symbol.toPrimitive hook is inspected via reflection, and type coercions execute?

    const s1 = Symbol('id');
    const s2 = Symbol('id');
    const s3 = Symbol.for('shared');
    const s4 = Symbol.for('shared');
    
    const user = {
      name: 'Alex',
      [s1]: 101,
      [Symbol.toPrimitive](hint) {
        if (hint === 'number') return 42;
        if (hint === 'string') return 'User:Alex';
        return 'Alex-default';
      }
    };
    
    const keysCount = Object.keys(user).length;
    const ownKeysCount = Reflect.ownKeys(user).length;
    const isSameGlobal = s3 === s4;
    const isSameLocal = s1 === s2;
    const numCoercion = +user;
    const strCoercion = `${user}`;
    
    console.log(
      keysCount,
      ownKeysCount,
      isSameGlobal,
      isSameLocal,
      numCoercion,
      strCoercion
    );
    Show the output
    1 3 true false 42 User:Alex
    Why it prints this, traced line by line
  40. 40 · Modern JavaScript: ES Modules, Iterators, and Weak Collections · Hard

    Proxy and Reflect Metaprogramming

    What is logged to the console when the following Proxy and Reflect operations execute across get, set, has, and deleteProperty traps?

    const target = { name: 'Alice', age: 28, _secret: 'shh' };
    const logs = [];
    
    const handler = {
      get(t, prop, receiver) {
        if (prop === 'tier') return 'Gold';
        return Reflect.get(t, prop, receiver);
      },
      set(t, prop, val, receiver) {
        if (prop === 'age' && (typeof val !== 'number' || val < 0)) {
          logs.push('invalid-age');
          return false;
        }
        return Reflect.set(t, prop, val, receiver);
      },
      has(t, prop) {
        if (typeof prop === 'string' && prop.startsWith('_')) return false;
        return Reflect.has(t, prop);
      },
      deleteProperty(t, prop) {
        if (prop === 'name') {
          logs.push('cant-delete');
          return false;
        }
        return Reflect.deleteProperty(t, prop);
      }
    };
    
    const proxy = new Proxy(target, handler);
    
    logs.push(proxy.tier);
    proxy.age = -5;
    proxy.age = 30;
    logs.push(proxy.age);
    logs.push('_secret' in proxy);
    delete proxy.name;
    logs.push(proxy.name);
    
    console.log(logs.join(' '));
    Show the output
    Gold invalid-age 30 false cant-delete Alice
    Why it prints this, traced line by line
  41. 41 · Debugging, Memory Leak Analysis, and Code Quality · Hard

    Memory Leaks & V8 GC

    What is logged to the console when an object is tracked in a root collection, its local variable binding is reassigned to null, and it is subsequently detached from the collection root?

    class MemoryTracker {
      constructor() {
        this.retainedRoots = new Set();
      }
      attach(obj) {
        this.retainedRoots.add(obj);
      }
      detach(obj) {
        this.retainedRoots.delete(obj);
      }
      isReachable(obj) {
        return this.retainedRoots.has(obj);
      }
    }
    
    const tracker = new MemoryTracker();
    
    let detachedDiv = { tag: 'div', id: 'dialog' };
    tracker.attach(detachedDiv);
    
    const ref1 = tracker.isReachable(detachedDiv);
    
    const originalRef = detachedDiv;
    detachedDiv = null;
    const ref2 = tracker.isReachable(originalRef);
    
    tracker.detach(originalRef);
    const ref3 = tracker.isReachable(originalRef);
    
    console.log(ref1, ref2, ref3, detachedDiv === null);
    Show the output
    true true false true
    Why it prints this, traced line by line
  42. 42 · Connecting JavaScript Runtime Mechanics to React Internals · Hard

    Closures & Stale State in React

    What is logged to the console when the following runtime simulation executes direct state updates, functional state updaters, a callback created in an earlier render, and a mutable ref?

    function createReactRuntime() {
      let committedState = 0;
    
      function render1() {
        const count = committedState;
        const staleCallback = () => count;
        const updateDirect = () => count + 1;
        const updateFunctional = (prev) => prev + 1;
        return { staleCallback, updateDirect, updateFunctional };
      }
    
      const r1 = render1();
    
      committedState = r1.updateDirect();
      committedState = r1.updateDirect();
      const countAfterDirect = committedState;
    
      committedState = r1.updateFunctional(committedState);
      committedState = r1.updateFunctional(committedState);
      const countAfterFunctional = committedState;
    
      const staleRead = r1.staleCallback();
    
      const ref = { current: 0 };
      ref.current = 3;
      const refRead = ref.current;
    
      return `${countAfterDirect} ${countAfterFunctional} ${staleRead} ${refRead}`;
    }
    
    const result = createReactRuntime();
    console.log(result);
    Show the output
    1 3 0 3
    Why it prints this, traced line by line