Skip to content

PUBLIC QUESTION PREVIEW

JavaScript / TypeScript interview questions

Closures, promises, prototypes, event loop, TypeScript — JS inside-out.

Showing 12 of 50 source questions. Sample answers are study material, not employer-specific hiring guidance.

How to work through this preview

Attempt each question before reading its answer. For a concept, give a definition and a concrete example. For code, state constraints, walk through a small input, and check complexity. For design, separate requirements from assumptions and explain failure handling. Use real situations for behavioral answers.

QUESTION 1 / easy / conceptual

What is a closure in JavaScript? Give a practical use case.

Sample answer

A closure is a function that retains access to variables from its enclosing scope even after the outer function has returned. Practical use: counter factory. function makeCounter() { let count = 0; return () => ++count; } const counter = makeCounter(); counter(); // 1, counter(); // 2 The inner function closes over "count". Used widely in: module pattern, event handlers with private state, memoization, debounce/throttle.

Hints to guide your next attempt

  • A function that "remembers" its outer scope even after that scope has finished executing

Source tags: closure / scope / javascript

QUESTION 2 / medium / conceptual

Explain the JavaScript event loop. What is the call stack, task queue, and microtask queue?

Sample answer

Call Stack: where synchronous code executes. One thread — one thing at a time. Task Queue (macrotask): setTimeout, setInterval, I/O callbacks. Processed one per event loop tick. Microtask Queue: Promise .then/.catch, queueMicrotask. Fully drained after each task, before the next macrotask. Order: current sync code → drain microtask queue → one macrotask → drain microtask queue → ... console.log('1'); setTimeout(() => console.log('3'), 0); Promise.resolve().then(() => console.log('2')); // Output: 1, 2, 3 — Promise runs before setTimeout.

Hints to guide your next attempt

  • Microtasks (Promises) run before macrotasks (setTimeout)
  • Event loop processes queues when the call stack is empty

Source tags: event-loop / promises / async / call-stack / javascript

QUESTION 3 / easy / conceptual

What is the difference between == and === in JavaScript? When does type coercion bite you?

Supplied choices

  1. true — both check value and type
  2. false — === checks value only, == checks value and type
  3. false — == does type coercion first, === checks value AND type strictly
  4. true — they are identical except == is faster

Source answer choice: C. false — == does type coercion first, === checks value AND type strictly

Sample answer

=== (strict equality): checks value AND type. 0 === false → false. == (loose equality): coerces types first. 0 == false → true. "" == 0 → true. null == undefined → true. Common gotchas: - [] == false → true (array coerced to "") - null == 0 → false (null only equals null and undefined with ==) - NaN == NaN → false (use Number.isNaN()) Best practice: always use ===. The only safe use of == is null checks: if (x == null) catches both null and undefined.

Hints to guide your next attempt

  • == does type coercion, === does not
  • null == undefined is true with ==

Source tags: equality / type-coercion / javascript

QUESTION 4 / medium / conceptual

What is "this" in JavaScript? How does it behave in arrow functions vs regular functions?

Sample answer

Regular function: "this" depends on how the function is called. In a method call obj.fn(), this = obj. In a plain call fn(), this = global (or undefined in strict mode). Arrow function: "this" is lexically inherited from the surrounding scope at the time the arrow function is defined. It never has its own "this". class Timer { constructor() { this.seconds = 0; } start() { setInterval(() => { this.seconds++; }, 1000); // arrow: this = Timer instance ✅ // setInterval(function() { this.seconds++; }, 1000); // regular: this = undefined ❌ } }

Hints to guide your next attempt

  • Regular function: this is determined at call time
  • Arrow function: this is lexically bound at definition time

Source tags: this / arrow-function / context / javascript

QUESTION 5 / medium / conceptual

What is Promise.all vs Promise.allSettled vs Promise.race?

Sample answer

Promise.all(promises): Resolves when ALL resolve. Rejects immediately if ANY rejects (fail-fast). Use when all results are required. Promise.allSettled(promises): Waits for ALL to finish regardless. Returns [{status: 'fulfilled', value}, {status: 'rejected', reason}]. Use when you want all results even on partial failure. Promise.race(promises): Resolves/rejects as soon as the FIRST one settles. Use for timeouts: Promise.race([fetchData(), timeout(5000)]). Promise.any(promises): Resolves when FIRST one fulfills. Rejects only if ALL reject. Opposite of race on rejection.

Hints to guide your next attempt

  • Think about what happens when one promise rejects
  • Race vs all — which resolves first wins vs all must resolve

Source tags: promises / async / javascript / concurrency

QUESTION 6 / easy / conceptual

What is the difference between var, let, and const? Explain hoisting.

Sample answer

var: function-scoped, hoisted and initialized as undefined. Can be redeclared. Avoid in modern code. let: block-scoped, hoisted but NOT initialized (temporal dead zone — accessing before declaration throws ReferenceError). Cannot be redeclared. const: same as let but must be initialized at declaration and cannot be reassigned (the reference is const, not the object's contents). Hoisting: JS moves declarations to the top of their scope during compilation. var x; is hoisted. let/const declarations are hoisted but sit in the "temporal dead zone" until the line of assignment.

Hints to guide your next attempt

  • var is function-scoped, let/const are block-scoped
  • Hoisting moves declarations to the top — but not initializations

Source tags: var / let / const / hoisting / scope / javascript

QUESTION 7 / medium / conceptual

How does the JavaScript prototype chain work? What happens when you access a property on an object?

Sample answer

Every JS object has an internal [[Prototype]] link (accessible via Object.getPrototypeOf or __proto__). When you access a property, JS first checks the object itself, then walks up the chain until it finds the property or reaches null. function Animal(name) { this.name = name; } Animal.prototype.speak = function() { return this.name + ' makes a sound'; }; const dog = new Animal('Rex'); dog.speak(); // found on Animal.prototype, not on dog itself dog.__proto__ === Animal.prototype // true Animal.prototype.__proto__ === Object.prototype // true Object.prototype.__proto__ === null // end of chain hasOwnProperty() checks only the object itself, not the chain. for...in iterates the entire chain. Object.keys() returns only own enumerable properties.

Hints to guide your next attempt

  • Every object has a [[Prototype]] internal slot
  • Property lookup walks up the chain until null

Source tags: prototype / prototype-chain / inheritance / javascript

QUESTION 8 / medium / conceptual

Explain Object.create(). How do you implement inheritance without using the class keyword?

Sample answer

Object.create(proto) creates a new object whose [[Prototype]] is set to proto. This is the low-level way to set up inheritance. const animal = { speak() { return this.name + ' speaks'; } }; const dog = Object.create(animal); dog.name = 'Rex'; dog.speak(); // 'Rex speaks' -- inherited from animal // Classical inheritance pattern without class: function Animal(name) { this.name = name; } Animal.prototype.speak = function() { return this.name; }; function Dog(name, breed) { Animal.call(this, name); // call parent constructor this.breed = breed; } Dog.prototype = Object.create(Animal.prototype); // set up chain Dog.prototype.constructor = Dog; // fix constructor reference Object.create(null) creates an object with NO prototype -- a pure hash map, useful for dictionaries without inherited properties like toString.

Hints to guide your next attempt

  • Object.create(proto) creates a new object whose [[Prototype]] is proto
  • Useful for pure prototype-based inheritance

Source tags: object-create / prototype / inheritance / javascript

QUESTION 9 / medium / conceptual

Explain ES6 class syntax. Is it true syntactic sugar over prototypes? What are static methods and private fields?

Sample answer

ES6 classes ARE syntactic sugar over the prototype system -- but with cleaner syntax and stricter semantics (class body runs in strict mode, class declarations have TDZ). class Animal { #sound = 'generic'; // private field (ES2022) constructor(name) { this.name = name; } speak() { return this.name + ' says ' + this.#sound; } // instance method on prototype static create(name) { return new Animal(name); } // on the constructor, not prototype } class Dog extends Animal { constructor(name) { super(name); // must call super before using 'this' this.#sound = 'woof'; // Error! private fields are not inherited } } Key differences from manual prototype setup: - Cannot call a class without new (throws TypeError) - Private fields (#) are truly private -- not accessible outside the class even with getOwnPropertyNames - static gets/sets are supported - extends and super() handle prototype chain setup automatically

Hints to guide your next attempt

  • class is syntactic sugar but with some new semantics (like TDZ for class declarations)
  • static methods live on the constructor, not the prototype

Source tags: class / extends / static / private-fields / javascript

QUESTION 10 / medium / conceptual

What is the difference between call(), apply(), and bind()? When would you use each?

Sample answer

All three methods set "this" explicitly on a function: call(thisArg, arg1, arg2, ...): invokes immediately, args passed individually. apply(thisArg, [arg1, arg2, ...]): invokes immediately, args passed as an array. bind(thisArg, arg1, ...): returns a NEW function with "this" permanently bound. Does not invoke. const user = { name: 'Ravin' }; function greet(greeting, punctuation) { return greeting + ', ' + this.name + punctuation; } greet.call(user, 'Hello', '!'); // 'Hello, Ravin!' greet.apply(user, ['Hello', '!']); // 'Hello, Ravin!' const boundGreet = greet.bind(user, 'Hello'); boundGreet('!'); // 'Hello, Ravin!' Use cases: - call: borrowing methods from other objects (Array.prototype.slice.call(arguments)) - apply: spreading an array as args before ES6 spread (Math.max.apply(null, arr)) - bind: event handlers that need a specific 'this', partial application

Hints to guide your next attempt

  • All three let you control what "this" is
  • bind returns a new function; call and apply invoke immediately

Source tags: call / apply / bind / this / javascript

QUESTION 11 / easy / conceptual

What is an IIFE? Why was it used and when is it still relevant?

Sample answer

IIFE (Immediately Invoked Function Expression) is a function that runs immediately after it is defined. (function() { const privateVar = 'cannot be accessed outside'; console.log('runs immediately'); })(); // Arrow function IIFE: (() => { /* code */ })(); Why it was used (pre-ES6): - var is function-scoped, not block-scoped. IIFE was the only way to create private scope. - Prevents global namespace pollution in scripts concatenated together. - Implements the Module pattern: expose only a public API. const counter = (function() { let count = 0; return { increment() { count++; }, value() { return count; } }; })(); counter.increment(); counter.value(); // 1 -- count is private Still relevant: - Top-level await alternative in some environments - Wrapping legacy code to prevent variable leakage - Modern use: mostly replaced by ES modules (import/export) which have their own scope

Hints to guide your next attempt

  • Immediately Invoked Function Expression
  • Creates a private scope in pre-ES6 code

Source tags: iife / scope / module-pattern / javascript

QUESTION 12 / hard / coding

What is currying in JavaScript? Implement a curry() function.

Sample answer

Currying transforms a function with multiple arguments into a sequence of functions, each taking one argument. // Manual curry: const add = a => b => c => a + b + c; add(1)(2)(3); // 6 // Generic curry implementation: function curry(fn) { return function curried(...args) { if (args.length >= fn.length) { return fn.apply(this, args); } return function(...moreArgs) { return curried.apply(this, args.concat(moreArgs)); }; }; } const add3 = curry((a, b, c) => a + b + c); add3(1)(2)(3); // 6 add3(1, 2)(3); // 6 -- partial application add3(1)(2, 3); // 6 Use cases: - Partial application: const add5 = add3(5); -- reusable specialized functions - Function composition pipelines - Functional libraries (Ramda, lodash/fp use auto-curry) - Event handler factories: const handleEvent = curry((type, handler, event) => ...)

Hints to guide your next attempt

  • Currying transforms f(a, b, c) into f(a)(b)(c)
  • Use function.length to know how many args are expected

Source tags: currying / partial-application / functional / javascript

Check understanding, not recognition

  • Can you explain the answer without reading it?
  • Can you show when the approach fails or needs a different assumption?
  • Can you connect the concept to a real project, task, or decision you have made?
  • Can you distinguish a simplified interview example from a production requirement?

A LITTLE MORE CLARITY

Frequently asked questions

How many JavaScript / TypeScript questions are shown here?

This public preview shows 12 questions with the supplied answers from the app's 50-question JavaScript / TypeScript bank. Full interactive practice requires signing in.

Should I memorize the sample answers?

Use them as reference explanations, not a script or a guarantee of technical correctness for every environment. Explain your assumptions, validate code against your language and version, and discuss trade-offs. Behavioral answers should be built from your own experience.

What do hints and solution steps mean?

Hints identify ideas to consider before reading the answer. When the source question includes steps, they are shown as a separate walkthrough. Example capacities and design targets in a solution are assumptions for that exercise, not real system statistics.

BUILD YOUR NEXT OPPORTUNITY

Practice JavaScript / TypeScript actively.

Sign in to use the full topic bank and interactive practice workspace.

Open Topic Practice