Exit
Learn Mode
Play Instead

JavaScript / Learn

Master 180 concepts with detailed explanations.

1basic

What is the output?

console.log(typeof null);
'object'

typeof null === 'object' is a long-standing bug in JavaScript that was never fixed for backwards-compatibility reasons. null is its own primitive type — not an object.

2basic

What is the output?

console.log(+true); console.log(typeof +true);
1 / 'number'

The unary plus (+) coerces its operand to a number. true converts to 1, so +true is 1. typeof 1 is 'number'.

3basic

What is the output?

console.log(!"Abhijeet"); console.log(typeof "Abhijeet");
false / 'string'

Non-empty strings are truthy. ! negates that truthy value to false. typeof operates on the original string literal 'Abhijeet', not the result of !, so it returns 'string'.

4basic

What is the output?

console.log(0.1 + 0.2 === 0.3);
false

0.1 + 0.2 produces 0.30000000000000004 due to IEEE 754 floating-point representation. It is not strictly equal to 0.3. Use Math.abs(a - b) < Number.EPSILON for safe float comparisons.

5medium

What is the output?

var x = 1; function test() { console.log(x); var x = 2; } test();
undefined

var declarations are hoisted to the top of their function scope and initialized as undefined, but the assignment stays in place. So console.log(x) sees the hoisted x (undefined) before x = 2 runs.

6basic

What is the output?

var greeter = "hey hi"; var times = 4; if (times > 3) { var greeter = "say Hello instead"; } console.log(greeter);
'say Hello instead'

var is function-scoped, not block-scoped. Redeclaring greeter inside the if block overwrites the same variable in the outer scope. The final value is 'say Hello instead'.

7basic

What is the output?

let greeting = "say Hi"; let times = 4; if (times > 3) { let hello = "say Hello instead"; console.log(hello); } console.log(hello);
'say Hello instead' / ReferenceError

let is block-scoped. hello exists only inside the if block, so the first console.log works fine. Outside the block, hello is not in scope — accessing it throws a ReferenceError.

8basic

What is the output?

var tester = "hey hi"; function newFunction() { var hello = "hello"; } console.log(hello);
ReferenceError

var is function-scoped. hello is declared inside newFunction and is completely invisible outside it. Accessing hello in the global scope throws a ReferenceError.

9medium

What is the output?

function fruit() { console.log(name); console.log(price); var name = "apple"; let price = 20; } fruit();
undefined / ReferenceError

var name is hoisted and initialized as undefined, so the first log prints undefined. let price is in the Temporal Dead Zone (TDZ) at the point of the second log, so accessing it throws a ReferenceError.

10medium

What is the output?

for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 1); }
3 / 3 / 3

var is function-scoped, so all three callbacks close over the same i variable. By the time the event loop runs them, the loop has finished and i is 3. Replacing var with let gives each iteration its own i, printing 0, 1, 2.

11basic

What is the output?

for (var j = 0; j < 10; j++) { // expression } console.log(j);
10

var is not block-scoped, so j leaks out of the for loop. The loop increments j until j < 10 fails, leaving j at 10. It is still accessible after the loop ends.

12basic

What is a closure in JavaScript?

A function that retains access to its outer scope variables even after the outer function has returned

A closure is formed when an inner function retains access to the lexical scope of its outer function, even after the outer function has finished executing. This enables data encapsulation and function factories.

13medium

What is the output?

function createCounter() { let count = 0; return { increment() { return ++count; }, getCount() { return count; } }; } const counter = createCounter(); counter.increment(); console.log(counter.count);
undefined

count is a private variable captured by the closure. The returned object only exposes increment() and getCount() — there is no count property on it. counter.count looks up a non-existent property, returning undefined.

14advanced

What is the output?

const calc = (a) => { return (b) => { if (b) return calc(a + b); return a; }; }; console.log(calc(1)(2)(3)(4)());
10

Each call returns a new function that accumulates the sum via closure. 1 + 2 + 3 + 4 = 10. The final empty call () receives no argument, so b is undefined (falsy) and the accumulated value 10 is returned.

15basic

What is the output?

const obj = { a: 1 }; const copy = obj; copy.a = 99; console.log(obj.a);
99

Objects are assigned by reference in JavaScript. copy and obj point to the same object in memory, so mutating copy.a also changes obj.a. The output is 99.

16basic

What is the output?

let c = { name: "Joe" }; let d; d = c; c.name = "peter"; console.log(d.name);
'peter'

d = c makes both variables reference the same object. Updating c.name to 'peter' is immediately visible through d because they share the same memory reference.

17medium

What is the output?

let data = { name: 'John' }; let data1 = { city: 'Mumbai', name: 'Joe' }; data = { ...data, ...data1 }; console.log(data);
{ name: 'Joe', city: 'Mumbai' }

When two spread objects share a key, the last one wins. data1 is spread after data, so its name 'Joe' overwrites data's 'John'. The final object is { name: 'Joe', city: 'Mumbai' }.

18medium

What is the output?

let data = { name: 'Abhijeet' }; let data1 = { city: 'Mumbai' }; data = { data, ...data1 }; console.log(data);
{ data: { name: 'Abhijeet' }, city: 'Mumbai' }

Without the spread (...), data is placed as a whole object under the literal key 'data'. Only data1 is spread into individual properties. Result: { data: { name: 'Abhijeet' }, city: 'Mumbai' }.

19medium

What is the output?

const person1 = { name: 'Abhijeet' }; const person2 = { name: 'Jeet' }; const person = Object.assign(person1, person2); console.log(person.name); console.log(person1.name);
'Jeet' / 'Jeet'

Object.assign(target, source) copies source properties into target and returns the same target object. person2 overwrites person1's name to 'Jeet'. Since person === person1, both log 'Jeet'.

20advanced

What is the output?

const a = {}; const b = { key: 'b' }; const c = { key: 'c' }; a[b] = 123; a[c] = 456; console.log(a[b]);
456

Plain object keys are always coerced to strings. Both b and c stringify to '[object Object]', so a[c] = 456 silently overwrites a[b] = 123. Reading a[b] returns 456.

21basic

What is the output?

let data = "size"; const bird = { size: "small" }; console.log(bird[data]); console.log(bird["size"]); console.log(bird.size); console.log(bird.data);
small / small / small / undefined

bird[data] evaluates the variable data to 'size', returning 'small'. bird['size'] and bird.size also access the same key. bird.data looks for a literal key named 'data' — which doesn't exist — returning undefined.

22medium

What is the output?

const property = 'firstName'; const name = 'Abhijeet'; const user = { property: name }; const user1 = { [property]: name }; console.log(user); console.log(user1);
{ property: 'Abhijeet' } / { firstName: 'Abhijeet' }

Without brackets, 'property' is used as the literal key name. With [property], JavaScript evaluates the variable and uses its value 'firstName' as the key. This is called a computed property name.

23advanced

What is the output?

console.log('A'); setTimeout(() => console.log('B'), 0); Promise.resolve().then(() => console.log('C')); console.log('D');
A / D / C / B

Synchronous code runs first: A, then D. Microtasks (Promise .then) always run before macrotasks (setTimeout). So C from the Promise runs before B from setTimeout. Order: A → D → C → B.

24advanced

What is the output?

const promise = () => Promise.resolve('Success'); function first() { promise().then(res => console.log(res)); console.log('First'); } async function second() { const res = await promise(); console.log(res); console.log('Second'); } first(); second();
First / Success / Success / Second

In first(), .then() is async so 'First' logs before its 'Success'. In second(), await pauses execution, so 'Second' comes after the awaited 'Success'. Microtask queue order: First → Success → Success → Second.

25medium

What is the output?

const fetchData = () => new Promise(res => res('One')); let isLoading = true; fetchData() .then(result => console.log(result)) .finally(() => { console.log('Two'); isLoading = false; }); console.log(isLoading);
true / One / Two

console.log(isLoading) is synchronous and executes first while isLoading is still true. .then() and .finally() are microtasks — they run after all synchronous code. Order: true → One → Two.

26medium

What does Promise.all() do when one of its promises rejects?

Immediately rejects with the reason of the first promise that rejected, discarding all other results

Promise.all() is fail-fast — it rejects immediately as soon as any one input promise rejects. Other pending promises continue running but their results are discarded. Use Promise.allSettled() when you need every outcome.

27advanced

What is the output?

let p = new Promise((resolve, reject) => { reject(Error('Failed!!')); }); p.catch(error => { console.log(error.message); }).then(result => { console.log(result); });
'Failed!!' / undefined

catch() handles the rejection and logs error.message ('Failed!!'). Since catch() has no explicit return, it implicitly returns undefined. That undefined becomes the resolved value passed to the chained then().

28advanced

What is the output?

function y() { console.log(1); setTimeout(() => console.log(2), 0); new Promise(resolve => { console.log(3); resolve(4); }); new Promise(resolve => { console.log(5); resolve(6); }).then(console.log); console.log(7); } y();
1 / 3 / 5 / 7 / 6 / 2

Synchronous: 1, 3, 5, 7. The first Promise resolves to 4 but has no .then(), so 4 is never logged. The second Promise's .then(console.log) schedules 6 as a microtask. setTimeout's 2 is a macrotask. Final order: 1 → 3 → 5 → 7 → 6 → 2.

29advanced

What is the output?

const func = (function(a) { delete a; return a; })(5); console.log(func);
5

The delete operator only removes object properties — it has no effect on local variables or function parameters. delete a does nothing here; the parameter a keeps its value of 5, which is returned and logged.

30medium

What is the output?

const result = false || {} || 20 || null; console.log(result);
{}

|| returns the first truthy value it encounters. false is falsy, but {} (an empty object) is truthy. Evaluation short-circuits at {} and returns it — 20 and null are never evaluated.

31medium

What is the output?

const result = null || false || ''; console.log(result);
'' (empty string)

When all operands are falsy, || returns the last one. null, false, and '' are all falsy, so the result is '' — the final value in the chain.

32medium

What is the output?

const result = [] || 0 || true; console.log(result);
[]

Empty arrays are truthy in JavaScript. || returns the first truthy value, which is []. Evaluation never reaches 0 or true.

33medium

What is the output?

console.log(null ?? 'default'); console.log(0 ?? 'default');
'default' / 0

?? (nullish coalescing) only falls back when the left side is null or undefined. Unlike ||, it does not treat 0, '', or false as nullish. null ?? 'default' → 'default'. 0 ?? 'default' → 0.

34medium

What is the output?

const person = { name: 'Sonu', displayName() { console.log(this.name); } }; const jayesh = Object.create(person); jayesh.displayName();
'Sonu'

Object.create(person) creates an empty object whose [[Prototype]] is set to person. jayesh has no own displayName method, so JavaScript walks the prototype chain, finds it on person, and calls it with jayesh as this. Since jayesh has no own name, it also walks the chain and finds 'Sonu' on person.

35advanced

What is the output?

let name = 'John'; function getName() { console.log(name); let name = 'Joe'; } getName();
ReferenceError

The inner let name shadows the outer one. let is hoisted but placed in the Temporal Dead Zone (TDZ) until its declaration is reached. The console.log hits the TDZ of the inner name — throwing a ReferenceError instead of falling back to the outer scope.

36medium

What is the output?

let name = 'John'; function getName() { let name; console.log(name); name = 'Joe'; } getName();
undefined

let name; declares the variable without a value. Unlike the TDZ case, the declaration exists before the log — so no error is thrown. An uninitialized let holds undefined until assigned.

37basic

What is the output?

const data = ['John', 'Joe', 'Sonu']; const [, m] = data; console.log(m);
'Joe'

Array destructuring assigns by position. The leading comma skips index 0 ('John'). m is bound to index 1 ('Joe'). The rest of the array is ignored.

38medium

What is the output?

const { name: fullName, age } = { name: 'Alice', age: 30 }; console.log(fullName, age);
'Alice' / 30

{ name: fullName } destructures the name property and binds its value to a local variable called fullName. age is destructured normally. Output: 'Alice' 30.

39basic

What is the output?

const name = 'John'; console.log(name());
TypeError

A string is a primitive — it is not callable. Invoking it with () throws a TypeError: name is not a function.

40basic

What does Array.prototype.reduce() do?

Executes a reducer callback on each element, carrying forward an accumulator to produce a single final value

reduce(callback, initialValue) calls callback(accumulator, currentValue) for every element and returns the final accumulated value. It can produce a number, string, object, or any other type from an array.

41basic

Which of these array methods returns a new array without mutating the original?

map() — applies a callback to every element and returns a brand-new array, leaving the original untouched

map() always returns a new array and never modifies the original. push(), splice(), and sort() all mutate the array in place, which is a common source of bugs when working with shared state.

42medium

What is the output?

const nums = [3, 1, 10, 2]; console.log(nums.sort());
[1, 10, 2, 3]

Without a comparator, sort() converts elements to strings and sorts lexicographically. '10' comes before '2' because '1' < '2'. Use nums.sort((a, b) => a - b) for numeric ordering.

43medium

What is the event loop responsible for in JavaScript?

Continuously monitoring the call stack and moving queued callbacks onto it as soon as the stack is empty

The event loop continuously checks if the call stack is empty. When it is, it dequeues the next callback — first from the microtask queue (Promises), then from the macrotask queue (setTimeout, setInterval).

44basic

What does the spread operator (...) do when used with an array?

Expands the array into its individual elements, which can then be passed as arguments or merged into a new array

The spread operator (...arr) expands an iterable into individual elements. Common uses: cloning ([...arr]), merging ([...a, ...b]), and spreading arguments into function calls (Math.max(...nums)).

45medium

What is the output?

const a = { x: 1, nested: { y: 2 } }; const b = { ...a }; b.nested.y = 99; console.log(a.nested.y);
99

Spread creates a shallow copy. Top-level primitives are copied by value, but nested objects are still shared by reference. Both a and b point to the same nested object, so mutating b.nested.y also changes a.nested.y.

46medium

What is the output?

const obj = { val: 10, getVal: function () { return this.val; }, }; const fn = obj.getVal; console.log(fn());
undefined

When getVal is assigned to fn and called as a plain function, it loses its obj context. In non-strict mode, this defaults to the global object, which has no val property — so this.val is undefined.

47medium

How does 'this' behave differently inside an arrow function vs a regular function?

Arrow functions capture 'this' from the surrounding lexical scope at the time they are defined and never rebind it

Arrow functions capture 'this' from their enclosing scope when they are defined and never change it. Regular functions get 'this' dynamically based on how they are called — different call sites can give different values.

48medium

What does Function.prototype.bind() return?

A new function with 'this' permanently fixed to the provided value, which can be called later with any arguments

bind(thisArg) returns a new function where 'this' is permanently bound to thisArg. Unlike call() and apply(), bind() does not invoke the function immediately — it hands back a reusable bound version.

49medium

What is event bubbling in JavaScript?

An event starts at the target element that was interacted with and travels upward through each ancestor to the document root

Bubbling is the default propagation behavior: an event starts at the target and travels upward through parent elements to the root. Event capturing is the opposite direction — root to target — and must be explicitly enabled.

50medium

What is the difference between an HTML attribute and a DOM property?

Attributes represent the initial static value written in HTML, while properties reflect the current live state of the DOM node

Attributes (written in HTML) are static — they represent the initial value and don't change on their own. Properties (on the DOM node) are live — they reflect the current state. An input's value attribute is its starting value; value property tracks what the user has typed.

51basic

Which of the following is fully hoisted — meaning both declaration AND initialization are moved to the top of scope?

Function declarations — both the name and the entire function body are available before the declaration line

Function declarations are fully hoisted — you can call them before they appear in the source. var is hoisted but only initialized to undefined (not its assigned value). let, const, and class are hoisted but stay in the Temporal Dead Zone until their declaration line.

52medium

What is the output?

console.log(greet()); function greet() { return 'Hello'; } const greet2 = function() { return 'Hi'; }; console.log(greet2());
'Hello' / 'Hi'

greet is a function declaration — fully hoisted, so calling it before the line it appears on works fine and returns 'Hello'. greet2 is a const holding a function expression. The const binding exists (it was hoisted) but greet2 is only called on the last line, after the assignment, so it resolves correctly and returns 'Hi'.

53basic

What is the key difference between == and === in JavaScript?

== performs implicit type coercion to make operands the same type before comparing, while === checks both value and type with no coercion at all

== (abstract equality) converts operands to the same type before comparing — '5' == 5 is true. === (strict equality) requires both value and type to match — '5' === 5 is false. Prefer === to avoid surprising coercion bugs.

54advanced

What is the output?

console.log([] == false); console.log([] === false);
true / false

[] == false triggers abstract equality coercion: [] → '' (via toString) → 0 (via ToNumber), and false → 0. 0 == 0 is true. [] === false is false immediately because they are different types (object vs boolean). No coercion happens with ===.

55basic

What is the output?

const arr = [1, 2, 3]; arr.push(4); console.log(arr);
[1, 2, 3, 4]

const prevents rebinding the variable (arr = something else would throw), but it does not freeze the object or array itself. push() mutates the array in place — the binding stays the same reference, so no error is thrown.

56medium

How do you create a truly immutable object in JavaScript?

Call Object.freeze() on it, which prevents adding, removing, or changing any of its own properties (shallow)

Object.freeze() prevents adding, removing, or changing properties on an object (shallow freeze). const only prevents reassigning the variable. Object.seal() prevents adding/removing but still allows value changes. Object.assign() creates a copy — it does nothing for immutability.

57medium

What does a generator function return when called?

An iterator object with a .next() method that resumes execution step by step each time it is called

Calling a generator function does not execute its body. It returns an iterator (Generator object) with a .next() method. Each .next() call resumes execution until the next yield or return, producing { value, done } objects.

58advanced

What is the output?

function* gen() { yield 1; yield 2; return 3; } const g = gen(); console.log(g.next()); console.log(g.next()); console.log(g.next());
{ value: 1, done: false } / { value: 2, done: false } / { value: 3, done: true }

Each .next() runs until the next yield or return. yield sets done: false; return sets done: true. So the first two .next() calls yield 1 and 2 with done: false. The third hits return 3 — value is 3, done is true.

59medium

What is a Symbol in JavaScript?

A guaranteed-unique, immutable primitive value primarily used as an object property key to avoid naming collisions

Symbol() creates a guaranteed-unique primitive. Two Symbol() calls with the same description are never equal: Symbol('x') !== Symbol('x'). Symbols are commonly used as non-string object keys to avoid naming conflicts with other libraries or framework internals.

60basic

What happens when you access a property on an object that doesn't have it?

JavaScript traverses the [[Prototype]] chain looking for the property; it returns the found value or undefined if the chain ends without a match

When a property isn't found on an object, the engine walks up the [[Prototype]] chain — checking each prototype object in turn. If found anywhere in the chain, that value is returned. If the chain ends at null (Object.prototype's prototype) without finding it, undefined is returned.

61medium

What is the output?

function Animal(name) { this.name = name; } Animal.prototype.speak = function() { return this.name + ' makes a sound.'; }; const dog = new Animal('Rex'); console.log(dog.speak()); console.log(dog.hasOwnProperty('speak'));
'Rex makes a sound.' / false

dog.speak() works because speak is found on Animal.prototype via the prototype chain. However, speak is not an own property of dog — it lives on the prototype. hasOwnProperty returns false for inherited properties.

62medium

Are JavaScript classes fundamentally different from constructor functions and prototypes?

No — classes are syntactic sugar over constructor functions and prototype chains, with a few stricter rules like mandatory new and no hoisting

ES6 classes are syntactic sugar. Under the hood, class Foo {} creates a constructor function. Methods defined in the class body are added to Foo.prototype. The prototype chain works identically to manually wired constructor functions.

63medium

What is the output?

class Shape { constructor(color) { this.color = color; } getColor() { return this.color; } } class Circle extends Shape { constructor(color, r) { super(color); this.radius = r; } } const c = new Circle('red', 5); console.log(c.getColor()); console.log(c instanceof Shape);
'red' / true

super(color) calls Shape's constructor, setting this.color. getColor() is inherited from Shape.prototype, so c.getColor() returns 'red'. instanceof checks the prototype chain — Circle.prototype inherits from Shape.prototype, so c instanceof Shape is true.

64basic

What is the output?

function riskyOp() { throw new TypeError('Bad input'); } try { riskyOp(); console.log('after'); } catch (e) { console.log(e instanceof TypeError, e.message); } finally { console.log('cleanup'); }
true 'Bad input' / cleanup

throw immediately exits riskyOp and jumps to catch — 'after' never logs. catch receives the TypeError, so e instanceof TypeError is true and e.message is 'Bad input'. finally always runs regardless of whether an error occurred, logging 'cleanup'.

65medium

Does the finally block run if the try block contains a return statement?

Yes — finally always executes before the caller receives the return value, even when the try block returns early

finally runs unconditionally — after try or catch, whether the block exits via normal completion, return, throw, or break. The return value is held until finally completes. If finally itself contains a return, it overrides the try's return value.

66basic

What is the difference between a named export and a default export in ES modules?

A module can have any number of named exports but at most one default export, and the import syntax is different for each type

Named exports (export const foo) can have many per file and must be imported with matching names: import { foo } from './mod'. A default export (export default) is one per file and can be imported with any name: import anything from './mod'.

67medium

What is a key difference between CommonJS require() and ES module import?

import is statically analyzed at parse time enabling tree-shaking, while require() is a runtime function call that can be used dynamically

ES module import is static: bundlers and engines can analyze dependencies at parse time, enabling tree-shaking and circular dependency detection. CommonJS require() is a runtime function call — you can use it conditionally, pass dynamic paths, and it runs when the line executes.

68medium

What makes an object iterable in JavaScript?

It must have a [Symbol.iterator]() method that returns an iterator object with a .next() method yielding { value, done } pairs

An object is iterable if it has a [Symbol.iterator]() method that returns an iterator (an object with .next() returning { value, done }). Arrays, strings, Maps, Sets, and generator objects are iterable by default. You can make any custom object iterable by implementing this protocol.

69basic

What is the output?

const str = 'hello'; const chars = [...str]; console.log(chars.length, chars[0]);
5 / 'h'

Strings are iterable — they implement [Symbol.iterator] that yields each Unicode character. Spreading a string into an array produces an array of individual characters. 'hello' has 5 characters; chars[0] is 'h'.

70medium

What is a key advantage of using Map over a plain object for key-value storage?

Map allows any value including objects, functions, and NaN as keys, and it preserves insertion order for all key types

Plain object keys are always coerced to strings (or Symbols). Map keys can be any value: objects, functions, numbers, NaN. Map also guarantees insertion-order iteration and provides a native .size property. Use Map when keys aren't strings or order matters.

71basic

What is the output?

const set = new Set([1, 2, 2, 3, 3, 3]); console.log(set.size); set.add(2); console.log(set.size);
3 / 3

Set stores only unique values. Passing [1, 2, 2, 3, 3, 3] results in {1, 2, 3} — size is 3. Adding 2 again has no effect because 2 already exists. Size remains 3.

72advanced

Why can WeakMap keys only be objects, not primitives?

WeakMap holds keys via weak references so entries are automatically removed when the key object is GC'd — primitives are never collected, so entries would leak forever

The 'weak' in WeakMap means the key is held by a weak reference — if no other reference to the key object exists, the GC can collect it and the entry disappears automatically. Primitives like numbers and strings live forever (they're value types), so allowing them as keys would defeat the memory-management purpose entirely.

73basic

What is the output?

const result = [1, 2, 3].reduce((acc, n) => acc + n, 10); console.log(result);
16

The second argument to reduce() is the initial accumulator value (10). The callback adds each element: 10 + 1 = 11, 11 + 2 = 13, 13 + 3 = 16.

74medium

What is the output?

const flat = [[1, 2], [3, [4, 5]]].flat(); console.log(flat);
[1, 2, 3, [4, 5]]

flat() with no argument defaults to depth 1. It flattens one level: the outer arrays are unwrapped, but the nested [4, 5] survives. Use flat(Infinity) to recursively flatten all nesting levels.

75basic

What is the difference between Array.prototype.find() and Array.prototype.filter()?

find() short-circuits and returns the first element for which the callback is truthy, or undefined if none match; filter() always runs to completion and returns a new array of all matches

find() short-circuits and returns the first element for which the callback returns true, or undefined if none match. filter() iterates the entire array and returns a new array containing every matching element. Neither mutates the original.

76basic

What does async before a function declaration always do to its return value?

Automatically wraps the return value in Promise.resolve(), meaning the function always returns a Promise no matter what it returns

An async function always returns a Promise. If the function returns a non-Promise value (e.g., 42), that value is automatically wrapped: Promise.resolve(42). If it throws, the returned Promise rejects with that error.

77basic

What is the output?

async function fetchUser() { return { id: 1, name: 'Alice' }; } fetchUser().then(u => console.log(u.name));
'Alice'

async functions always return a Promise. The returned object is the resolved value, accessible in .then(). u is { id: 1, name: 'Alice' }, so u.name is 'Alice'.

78medium

What is the output?

async function run() { try { const result = await Promise.reject(new Error('oops')); console.log(result); } catch (e) { console.log('caught:', e.message); } } run();
'caught: oops'

await unwraps a rejected Promise and throws the rejection reason as an error inside the async function. try/catch catches it. e.message is 'oops', so the output is 'caught: oops'.

79basic

What is the difference between call() and apply()?

Both invoke the function immediately with a given 'this', but call() receives extra arguments individually while apply() receives them as a single array

Both call() and apply() invoke the function immediately with a specified 'this'. The only difference is argument passing: fn.call(ctx, a, b) vs fn.apply(ctx, [a, b]). bind() is the version that does not invoke immediately — it returns a new bound function.

80medium

What is the output?

function greet(greeting, punctuation) { return greeting + ', ' + this.name + punctuation; } const user = { name: 'Abhijeet' }; console.log(greet.call(user, 'Hello', '!')); console.log(greet.apply(user, ['Hi', '?']));
'Hello, Abhijeet!' / 'Hi, Abhijeet?'

call(user, 'Hello', '!') sets this to user and passes arguments individually. apply(user, ['Hi', '?']) does the same but receives arguments as an array. In both cases, this.name resolves to 'Abhijeet'.

81basic

What is an IIFE and why would you use one?

Immediately Invoked Function Expression — a function defined and called in one step, creating a private scope that prevents its variables from leaking into the global namespace

An IIFE (Immediately Invoked Function Expression) is a function defined and called in one expression: (function() { ... })(). Variables declared inside are scoped to that function and don't leak to the global scope. Before ES modules, IIFEs were the primary tool for avoiding global namespace pollution.

82medium

What is function currying?

Transforming a multi-argument function into a sequence of single-argument functions, each returning the next until all arguments are satisfied

Currying transforms f(a, b, c) into f(a)(b)(c). Each call returns a new function waiting for the next argument. It enables partial application — fixing some arguments ahead of time to create specialized functions — and is heavily used in functional programming patterns.

83medium

What is the output?

const multiply = a => b => a * b; const double = multiply(2); console.log(double(5)); console.log(multiply(3)(4));
10 / 12

multiply(2) returns b => 2 * b, assigned to double. double(5) returns 2 * 5 = 10. multiply(3)(4) returns 3 * 4 = 12.

84medium

What is memoization?

An optimization where a function stores its results keyed by input arguments and returns the cached result on subsequent calls with the same arguments

Memoization stores the result of a pure function call keyed by its arguments. On subsequent calls with identical arguments, the cached result is returned without re-executing the function body. It trades memory for speed and is most beneficial for expensive, frequently called pure functions.

85medium

Which of the following is a pure function?

function add(a, b) { return a + b; }

A pure function has two requirements: (1) same input always produces same output, and (2) no side effects. Option A has a side effect (console.log). Option B's output changes over time. Option D mutates the input array. Only option C is deterministic and side-effect-free.

86medium

What is the output?

const user = { profile: null }; console.log(user?.profile?.name); console.log(user?.address?.city ?? 'Unknown');
undefined / 'Unknown'

user?.profile returns null. null?.name short-circuits immediately and returns undefined (not a TypeError). user?.address returns undefined (no address property), so undefined?.city is also undefined. undefined ?? 'Unknown' falls back to 'Unknown' because undefined is nullish.

87basic

What is optional chaining (?.) designed to solve?

Safely reading deeply nested properties by short-circuiting to undefined instead of throwing a TypeError when an intermediate value is null or undefined

Without ?., accessing a.b.c throws a TypeError if a.b is null or undefined. Optional chaining short-circuits the entire expression to undefined when it encounters a nullish value, eliminating the need for manual if (a && a.b && a.b.c) guards.

88basic

What is the output?

const name = 'World'; const msg = `Hello, ${name}!`; console.log(typeof msg, msg);
'string' / 'Hello, World!'

Template literals are still strings — typeof returns 'string'. The ${name} interpolation is resolved at evaluation time, producing 'Hello, World!'. Template literals only become tagged templates when preceded by a tag function.

89basic

Which of these is a falsy value in JavaScript?

0 (zero)

JavaScript's falsy values are: false, 0, -0, 0n (BigInt zero), '' (empty string), null, undefined, and NaN — eight in total. 0 is one of them. 'false' (non-empty string), [] (object), and {} (object) are all truthy — including empty arrays and objects.

90basic

What is the output?

console.log(Boolean('')); console.log(Boolean(0)); console.log(Boolean([])); console.log(Boolean({}));
false / false / true / true

'' is an empty string (falsy) → false. 0 is falsy → false. [] is an empty array — but all objects (including arrays) are truthy → true. {} is an empty object, also truthy → true.

91medium

What is the output?

console.log(1 + '2'); console.log('3' - 1); console.log('6' / '2');
'12' / 2 / 3

1 + '2': + with a string triggers string concatenation → '12'. '3' - 1: - has no string behavior, so '3' is coerced to the number 3 → 2. '6' / '2': / coerces both strings to numbers → 3. Arithmetic operators other than + always convert to numbers.

92medium

Which garbage collection algorithm does JavaScript primarily use?

Mark-and-sweep — starting from root references, the GC marks every reachable object, then frees everything that was not marked

Modern JavaScript engines (V8, SpiderMonkey) use mark-and-sweep. Starting from roots (global, stack), the GC marks every reachable object. Anything unmarked is considered garbage and freed. This correctly handles circular references, which pure reference counting cannot.

93medium

What is the output?

const obj = { a: 1, b: undefined, c: function() {}, d: null }; console.log(JSON.stringify(obj));
'{"a":1,"d":null}'

JSON.stringify() silently omits properties whose values are undefined, functions, or Symbols. null is a valid JSON value and is kept. So only a and d make it into the output string.

94advanced

What is a JavaScript Proxy?

An object that wraps a target object and intercepts fundamental operations like property access, assignment, and deletion through customizable handler traps

Proxy lets you define custom behavior for fundamental operations on an object. You provide handler traps (get, set, has, deleteProperty, etc.) that run when those operations are performed. Vue 3 uses Proxy for its reactivity system; it's also used for validation, logging, and virtual DOM patterns.

95advanced

What problem does tail call optimization (TCO) solve in recursive functions?

It reuses the current stack frame instead of pushing a new one when a recursive call is in tail position, preventing stack overflow on deep recursion

In a tail call, the recursive call is the very last thing the function does — so the current stack frame is no longer needed. TCO reuses the same frame instead of pushing a new one, keeping stack depth constant. ES6 mandates TCO in strict mode, though most engines only partially implement it.

96medium

What is the scope chain in JavaScript?

The series of nested lexical environments the engine traverses to resolve a variable name, moving outward from the current scope until found or global is reached

Every function carries a reference to the environment it was defined in. When resolving a variable, JavaScript checks the current scope first, then follows the outer environment reference up the chain until it finds the variable or reaches the global scope. This chain is fixed at definition time (lexical scope), not call time.

97medium

What is an execution context in JavaScript?

An internal data structure the engine creates for every code block that runs, storing the variable environment, outer scope reference, and 'this' binding

Every time code runs, the engine creates an execution context: a structure containing the variable environment (where declared variables live), the scope chain (outer environment references), and the value of 'this'. There is a global execution context and one created for each function call. These are pushed/popped on the call stack.

98medium

What is the difference between debounce and throttle?

Debounce resets a timer on every call and fires only after the calls stop for a set period; throttle fires at most once per interval no matter how many calls come in

Debounce: resets a timer each call and fires only after calls stop for the specified delay — good for search-as-you-type (fire after the user pauses). Throttle: fires at most once per interval no matter how fast calls come in — good for scroll/resize handlers to limit rate.

99advanced

What is the output?

const obj = {}; Object.defineProperty(obj, 'secret', { value: 42, writable: false, enumerable: false, }); obj.secret = 100; console.log(obj.secret); console.log(Object.keys(obj));
42 / []

writable: false means silent assignments are ignored in non-strict mode (a TypeError in strict mode). The value stays 42. enumerable: false hides the property from Object.keys(), JSON.stringify(), and for...in loops. It still exists and is readable; it's just hidden from enumeration.

100medium

What is the output?

const arr = [1, 2, 3]; arr[10] = 99; console.log(arr.length); console.log(arr[5]);
11 / undefined

Setting arr[10] = 99 makes the array sparse — indices 3 through 9 are empty slots. length becomes 11 (highest index + 1). Accessing arr[5] returns undefined because the slot is empty, not because a value of undefined was stored there.

101medium

What is the output?

console.log(NaN === NaN); console.log(Number.isNaN(NaN)); console.log(Number.isNaN('NaN'));
false / true / false

NaN is the only JavaScript value that is not equal to itself. NaN === NaN is false. Number.isNaN() checks strictly — it returns true only for the actual NaN value, not for strings that look like 'NaN'. The global isNaN() would coerce 'NaN' to NaN and return true, but Number.isNaN() does not coerce.

102medium

What is the output?

function outer() { let x = 10; return function inner() { x++; return x; }; } const fn1 = outer(); const fn2 = outer(); console.log(fn1()); console.log(fn1()); console.log(fn2());
11 / 12 / 11

Each call to outer() creates a new closure with its own independent x variable. fn1 and fn2 have separate x values, both starting at 10. fn1() increments its x to 11, then 12. fn2() starts fresh from 10, increments to 11 — independent of fn1's state.

103medium

What is the output?

const obj = { value: 1, double: function() { return () => this.value * 2; } }; console.log(obj.double()());
2

double is a regular method so 'this' is obj when called as obj.double(). It returns an arrow function, which captures 'this' from double's lexical scope — still obj. So the arrow function returns obj.value * 2 = 1 * 2 = 2.

104basic

What is the output?

const nums = [1, 2, 3, 4, 5]; const result = nums .filter(n => n % 2 === 0) .map(n => n * 3); console.log(result);
[6, 12]

filter(n => n % 2 === 0) keeps even numbers: [2, 4]. map(n => n * 3) multiplies each by 3: [6, 12]. The odd numbers 1, 3, 5 are discarded by filter and never reach map.

105advanced

What is the output?

let a = 3; let b = new Number(3); console.log(a == b); console.log(a === b);
true / false

new Number(3) creates a Number object wrapper, not a primitive. == coerces it: the object is unwrapped to its primitive value 3, so 3 == 3 is true. === checks type too — a is a number primitive, b is an object — different types, so false.

106basic

What is the output?

const [a, b, ...rest] = [1, 2, 3, 4, 5]; console.log(a, b, rest);
1 / 2 / [3, 4, 5]

Rest syntax in destructuring collects remaining elements into an array. a gets 1, b gets 2, and rest gets all remaining elements [3, 4, 5]. The rest element must always be last in the destructuring pattern.

107basic

What is the output?

function test(...args) { console.log(args.length); console.log(Array.isArray(args)); } test(1, 2, 3);
3 / true

Rest parameters collect all passed arguments into a real Array. args is [1, 2, 3], so args.length is 3 and Array.isArray(args) is true. This contrasts with the legacy arguments object, which is array-like but not a real Array.

108advanced

What is the output?

class Counter { #count = 0; increment() { this.#count++; } get value() { return this.#count; } } const c = new Counter(); c.increment(); c.increment(); console.log(c.value); console.log(c.count);
2 / undefined

Private class fields (prefixed with #) are not exposed as regular properties. c.value returns 2 through the getter, which has internal access to #count. c.count (no #) looks for a regular property named 'count' on the instance — it doesn't exist, so it returns undefined. The private field #count is completely inaccessible from outside the class body.

109medium

What is the output?

const promise1 = Promise.resolve(1); const promise2 = Promise.resolve(2); const promise3 = Promise.reject(3); Promise.allSettled([promise1, promise2, promise3]) .then(results => console.log(results.map(r => r.status)));
['fulfilled', 'fulfilled', 'rejected']

Promise.allSettled() waits for every promise to settle (unlike Promise.all() which rejects fast). Each result object has a status of 'fulfilled' or 'rejected'. The rejection of promise3 doesn't abort the operation — all three results are collected.

110advanced

What is the output?

const obj = { x: 1 }; const handler = { get(target, key) { return key in target ? target[key] : 'not found'; } }; const proxy = new Proxy(obj, handler); console.log(proxy.x); console.log(proxy.y);
1 / 'not found'

The Proxy's get trap intercepts all property access. For proxy.x, key 'x' exists in target so target[key] = 1 is returned. For proxy.y, 'y' is not in target so the trap returns 'not found' instead of undefined.

111basic

What is the output?

Promise.resolve(1) .then(x => x + 1) .then(x => x * 2) .then(x => console.log(x));
4

Each .then() returns a new Promise with the handler's return value. 1 + 1 = 2, then 2 * 2 = 4. The final .then logs 4.

112medium

What is the output?

Promise.resolve('start') .then(v => { console.log(v); return 'middle'; }) .then(v => { console.log(v); }) .then(v => console.log(v));
'start' / 'middle' / undefined

First .then logs 'start' and returns 'middle'. Second .then logs 'middle' but has no return — implicit undefined. Third .then receives and logs undefined.

113medium

What is the output?

const p = Promise.reject('error'); p.catch(e => { console.log('caught', e); return 'recovered'; }).then(v => console.log(v));
'caught error' / 'recovered'

.catch() handles the rejection, logs 'caught error', and returns 'recovered'. A .catch() that returns a value produces a fulfilled Promise, so the chained .then() receives 'recovered' and logs it.

114basic

What is the output?

async function getData() { return await Promise.resolve(42); } getData().then(console.log);
42

await unwraps the resolved value 42. The async function returns a Promise that resolves with 42. .then(console.log) prints 42.

115medium

What is the output?

console.log('1'); async function main() { console.log('2'); await null; console.log('3'); } main(); console.log('4');
1 / 2 / 4 / 3

'1' logs synchronously. main() is called — '2' logs synchronously inside it. await null suspends main() and schedules the rest as a microtask. Control returns to the caller, '4' logs. Then the microtask runs and '3' logs.

116medium

What is the output?

async function fail() { throw new Error('boom'); } fail() .catch(e => console.log(e.message)) .then(() => console.log('done'));
'boom' / 'done'

An async function that throws returns a rejected Promise. .catch() handles the rejection and logs e.message ('boom'). Since .catch() returns undefined (no explicit return), the chained .then() runs and logs 'done'.

117basic

What is the output?

Promise.all([ Promise.resolve(1), Promise.resolve(2), Promise.resolve(3), ]).then(console.log);
[1, 2, 3]

Promise.all() waits for all promises to fulfill and resolves with an array of their results in the same order they were passed. console.log([1, 2, 3]) prints the array.

118medium

What is the output?

const delay = ms => new Promise(res => setTimeout(res, ms)); async function run() { await delay(0); console.log('A'); } run(); console.log('B');
'B' / 'A'

run() is called and immediately hits await delay(0). setTimeout(0) is a macrotask — it yields control. 'B' logs synchronously. After all synchronous code and microtasks finish, the setTimeout callback fires, resolving the delay, and 'A' logs.

119basic

What is the output?

async function one() { return 1; } async function two() { return 2; } async function run() { const a = await one(); const b = await two(); console.log(a + b); } run();
3

await one() resolves to 1, await two() resolves to 2. a + b = 3. console.log prints 3.

120basic

What is the output?

Promise.race([ new Promise(res => setTimeout(() => res('slow'), 100)), new Promise(res => setTimeout(() => res('fast'), 10)), ]).then(console.log);
'fast'

Promise.race() resolves or rejects as soon as the first promise settles. The 10ms promise resolves first with 'fast', so that is the resolved value.

121advanced

What is the output?

let x = 0; new Promise(resolve => { x = 1; resolve(x); x = 2; }).then(val => console.log(val, x));
1 / 2

The Promise executor runs synchronously. x is set to 1, then resolve(1) is called — the resolved value is captured as 1. x is then set to 2. When the .then() microtask runs, val is 1 (the captured value) but x is now 2.

122medium

What is the output?

async function run() { const results = await Promise.all([ Promise.resolve('a'), Promise.reject('b'), Promise.resolve('c'), ]); console.log(results); } run().catch(e => console.log('caught:', e));
'caught: b'

Promise.all() rejects immediately when any promise rejects. 'b' is the rejection reason. The await throws, the async function rejects, and the outer .catch() logs 'caught: b'.

123medium

What is the output?

async function run() { console.log('start'); await Promise.resolve(); console.log('middle'); await Promise.resolve(); console.log('end'); } run(); console.log('sync');
'start' / 'sync' / 'middle' / 'end'

'start' logs synchronously. First await suspends — 'sync' logs. Microtask resumes: 'middle' logs. Second await suspends briefly again. Microtask resumes: 'end' logs.

124medium

What is the output?

const p = new Promise((resolve) => { resolve(1); resolve(2); }); p.then(console.log);
1

A Promise can only settle once. The first resolve(1) transitions it to fulfilled with value 1. The second resolve(2) is silently ignored — the state is already locked. .then() receives 1.

125basic

What is the output?

const arr = [1, 2, 3]; const result = arr.map((n, i) => n * i); console.log(result);
[0, 2, 6]

map passes (element, index) to the callback. 1 * 0 = 0, 2 * 1 = 2, 3 * 2 = 6. Result: [0, 2, 6].

126basic

What is the output?

const arr = [1, [2, [3, [4]]]]; console.log(arr.flat(Infinity));
[1, 2, 3, 4]

flat(Infinity) recursively flattens all nesting levels. The result is a fully flat array [1, 2, 3, 4].

127medium

What is the output?

const words = ['hello', 'world']; const result = words.flatMap(w => w.split('')); console.log(result.length);
10

flatMap maps each word to its character array then flattens one level. 'hello' → ['h','e','l','l','o'] (5 chars) + 'world' → ['w','o','r','l','d'] (5 chars) = 10 elements.

128basic

What is the output?

const arr = [3, 1, 4, 1, 5]; const unique = [...new Set(arr)]; console.log(unique);
[3, 1, 4, 5]

new Set() removes duplicates while preserving insertion order. 1 appears at index 1 first, so the second 1 is dropped. Spreading back to an array gives [3, 1, 4, 5].

129basic

What is the output?

const arr = [1, 2, 3, 4, 5]; console.log(arr.slice(1, 3));
[2, 3]

slice(start, end) returns elements from index start up to but NOT including index end. slice(1, 3) returns indices 1 and 2: [2, 3].

130medium

What is the output?

const arr = [1, 2, 3]; arr.splice(1, 1, 9, 10); console.log(arr);
[1, 9, 10, 3]

splice(1, 1, 9, 10) starts at index 1, removes 1 element (the 2), and inserts 9 and 10 in its place. Original [1, 2, 3] becomes [1, 9, 10, 3].

131medium

What is the output?

const arr = [1, 2, 3, 4]; const evens = arr.filter(Boolean); console.log(evens);
[1, 2, 3, 4]

filter(Boolean) removes falsy values. All elements — 1, 2, 3, 4 — are truthy numbers, so none are removed. The result is the same array contents [1, 2, 3, 4].

132basic

What is the output?

const arr = [0, 1, '', null, undefined, false, 2]; const truthy = arr.filter(Boolean); console.log(truthy);
[1, 2]

filter(Boolean) keeps only truthy values. 0, '', null, undefined, and false are all falsy and get removed. Only 1 and 2 survive.

133basic

What is the output?

const arr = ['a', 'b', 'c']; console.log(arr.indexOf('b')); console.log(arr.indexOf('z'));
1 / -1

'b' is at index 1. indexOf returns -1 when the element is not found — it never returns undefined or null.

134basic

What is the output?

const arr = [1, 2, 3]; console.log(arr.every(n => n > 0)); console.log(arr.some(n => n > 2));
true / true

every() returns true only if ALL elements pass the test. 1, 2, 3 are all > 0 → true. some() returns true if AT LEAST ONE element passes. 3 > 2 → true.

135medium

What is the output?

const matrix = [[1, 2], [3, 4]]; const flat = matrix.reduce((acc, row) => acc.concat(row), []); console.log(flat);
[1, 2, 3, 4]

Starting with [], reduce concatenates each row array into the accumulator. [] + [1,2] = [1,2], then [1,2] + [3,4] = [1,2,3,4].

136basic

What is the output?

const obj = { a: 1, b: 2, c: 3 }; console.log(Object.keys(obj)); console.log(Object.values(obj));
['a', 'b', 'c'] / [1, 2, 3]

Object.keys() returns an array of the object's own enumerable property names. Object.values() returns an array of the corresponding values.

137basic

What is the output?

const obj = { x: 1, y: 2 }; const entries = Object.entries(obj); console.log(entries);
[['x', 1], ['y', 2]]

Object.entries() returns an array of [key, value] pairs for every own enumerable property.

138medium

What is the output?

const pairs = [['a', 1], ['b', 2], ['c', 3]]; const obj = Object.fromEntries(pairs); console.log(obj);
{ a: 1, b: 2, c: 3 }

Object.fromEntries() is the inverse of Object.entries() — it converts an iterable of [key, value] pairs into an object.

139medium

What is the output?

const obj = { a: 1 }; Object.freeze(obj); obj.a = 99; obj.b = 2; console.log(obj);
{ a: 1 }

Object.freeze() prevents all mutations to the object. In non-strict mode, attempts to modify or add properties are silently ignored. obj stays { a: 1 }.

140medium

What is the output?

const { a, b = 10, c = 20 } = { a: 1, b: undefined }; console.log(a, b, c);
1 / 10 / 20

Destructuring defaults apply when the value is undefined. b is explicitly undefined in the source, so the default 10 is used. c is missing entirely, so 20 is used. a gets 1.

141basic

What is the output?

const str = 'JavaScript'; console.log(str.slice(0, 4)); console.log(str.slice(-6));
'Java' / 'Script'

slice(0, 4) gives characters at indices 0–3: 'Java'. slice(-6) counts 6 from the end of 'JavaScript' (length 10), starting at index 4: 'Script'.

142basic

What is the output?

const str = ' hello world '; console.log(str.trim().split(' ').length);
2

trim() removes leading and trailing whitespace: 'hello world'. split(' ') splits on the single space between the words: ['hello', 'world']. Length is 2.

143basic

What is the output?

console.log('abc'.padStart(5, '0')); console.log('abc'.padEnd(5, '-'));
'00abc' / 'abc--'

padStart pads to total length 5 by adding fill characters at the START: '00abc'. padEnd pads at the END: 'abc--'.

144basic

What is the output?

const str = 'hello'; console.log(str.includes('ell')); console.log(str.startsWith('he')); console.log(str.endsWith('lo'));
true / true / true

'ell' is a substring of 'hello' → true. 'hello' starts with 'he' → true. 'hello' ends with 'lo' → true.

145basic

What is the output?

console.log('ha'.repeat(3)); console.log('abc'.replace('b', 'X')); console.log('aabbcc'.replaceAll('b', 'Y'));
'hahaha' / 'aXc' / 'aaYYcc'

repeat(3) produces 'hahaha'. replace() replaces only the first match: 'aXc'. replaceAll() replaces every match: both 'b's become 'Y' → 'aaYYcc'.

146medium

What is the output?

console.log(Math.max(1, 3, 2)); console.log(Math.max()); console.log(Math.min());
3 / -Infinity / Infinity

Math.max(1,3,2) is 3. Math.max() with no arguments returns -Infinity (identity element for max). Math.min() with no arguments returns Infinity (identity element for min).

147medium

What is the output?

console.log(parseInt('10', 2)); console.log(parseInt('10', 16)); console.log(parseInt('10.9'));
2 / 16 / 10

parseInt('10', 2) parses '10' in base 2 → 2. parseInt('10', 16) parses '10' in hex → 16. parseInt('10.9') parses the integer part only → 10.

148medium

What is the output?

console.log(typeof NaN); console.log(isNaN('hello')); console.log(Number.isNaN('hello'));
'number' / true / false

typeof NaN is 'number'. The global isNaN() coerces its argument: 'hello' becomes NaN → returns true. Number.isNaN() does NOT coerce — 'hello' is a string, not NaN → returns false.

149basic

What is the output?

let count = 0; const inc = () => ++count; const dec = () => --count; inc(); inc(); dec(); console.log(count);
1

Both arrow functions close over the same count variable. inc() twice: 0→1→2. dec() once: 2→1. Final value is 1.

150basic

What is the output?

function makeAdder(x) { return function(y) { return x + y; }; } const add5 = makeAdder(5); console.log(add5(3)); console.log(add5(7));
8 / 12

makeAdder(5) returns a closure that adds 5 to its argument. add5(3) = 5+3 = 8. add5(7) = 5+7 = 12.

151advanced

What is the output?

(function() { var a = b = 3; })(); console.log(typeof a); console.log(typeof b);
'undefined' / 'number'

var a = b = 3 is parsed as b = 3 (implicit global) then var a = b. Inside the IIFE, a is local (var) and b becomes a global. Outside: typeof a is 'undefined' (a doesn't exist in this scope). typeof b is 'number' (b leaked globally).

152medium

What is the output?

let i = 0; const fns = []; for (let i = 0; i < 3; i++) { fns.push(() => i); } console.log(fns[0](), fns[1](), fns[2]());
0 1 2

The loop uses let, so each iteration creates a new binding for i. Each closure captures its own unique i: 0, 1, 2 respectively. The outer let i = 0 is shadowed and irrelevant.

153medium

What is the output?

const obj = { name: 'Alice', greet: function() { return `Hi, I'm ${this.name}`; } }; const { greet } = obj; console.log(greet());
"Hi, I'm undefined"

Destructuring extracts greet as a standalone function. When called without a receiver, this defaults to the global object (or undefined in strict mode), which has no name property. this.name is undefined.

154medium

What is the output?

function Person(name) { this.name = name; } const p = new Person('Bob'); console.log(p instanceof Person); console.log(p.constructor === Person);
true / true

new Person creates an object whose [[Prototype]] is Person.prototype, so instanceof returns true. constructor is found on Person.prototype and points back to Person, so === comparison is true.

155medium

What is the output?

class Base { greet() { return 'Hello from Base'; } } class Child extends Base { greet() { return super.greet() + ' and Child'; } } console.log(new Child().greet());
'Hello from Base and Child'

super.greet() calls the Base class's greet method, returning 'Hello from Base'. The Child method appends ' and Child', producing 'Hello from Base and Child'.

156medium

What is the output?

const obj = { a: 1, b: { c: 2 } }; const clone = JSON.parse(JSON.stringify(obj)); clone.b.c = 99; console.log(obj.b.c);
2

JSON.parse(JSON.stringify(obj)) creates a true deep clone — nested objects are also copied. Mutating clone.b.c does not affect obj.b.c, which stays 2.

157basic

What is the output?

const a = [1, 2, 3]; const b = [1, 2, 3]; console.log(a == b); console.log(a === b);
false / false

Arrays are objects. Both == and === compare object references, not contents. a and b are separate objects in memory, so both comparisons return false.

158medium

What is the output?

const obj = {}; console.log(obj.toString()); console.log(obj.hasOwnProperty('toString'));
'[object Object]' / false

toString() is inherited from Object.prototype and returns '[object Object]'. It is NOT an own property of obj, so hasOwnProperty('toString') returns false.

159medium

What is the output?

console.log(2 ** 10); console.log(5 % 3); console.log(-7 % 3);
1024 / 2 / -1

** is the exponentiation operator: 2**10 = 1024. 5 % 3 = 2. In JavaScript, % preserves the sign of the dividend: -7 % 3 = -1.

160basic

What is the output?

const obj = { a: 1, b: 2 }; for (const key in obj) { console.log(key); }
'a' / 'b'

for...in iterates over the enumerable property NAMES (keys) of an object, not its values. It logs 'a' then 'b'.

161advanced

What is the output?

function test() { return { value: 42 } } console.log(test());
undefined

Automatic Semicolon Insertion (ASI) adds a semicolon after return on its own line. The function returns undefined. The object literal on the next line is dead code.

162basic

What is the output?

const x = 5; const result = x > 3 ? x > 4 ? 'big' : 'medium' : 'small'; console.log(result);
'big'

x = 5. 5 > 3 is true, so evaluate the nested ternary: 5 > 4 is true → 'big'. Result is 'big'.

163basic

What is the output?

let a = 1; let b = 2; [a, b] = [b, a]; console.log(a, b);
2 / 1

Array destructuring swaps a and b without a temporary variable. The right side [b, a] = [2, 1] is evaluated first, then a gets 2 and b gets 1.

164medium

What is the output?

const obj = { val: 42, getVal: () => this?.val }; console.log(obj.getVal());
undefined

Arrow functions do not have their own 'this' — they inherit it from the enclosing lexical scope. At the top level (or module), this is undefined (strict) or the global object (which has no val property). this?.val short-circuits to undefined.

165medium

What is the output?

function greet(name = 'stranger') { return `Hello, ${name}!`; } console.log(greet()); console.log(greet(undefined)); console.log(greet(null));
'Hello, stranger!' / 'Hello, stranger!' / 'Hello, null!'

Default parameters apply only when the argument is undefined (or not passed). greet() and greet(undefined) both trigger the default 'stranger'. greet(null) passes null explicitly — null is not undefined, so it is used as-is.

166basic

What is the output?

const arr = [1, 2, 3, 4, 5]; console.log(arr.at(0)); console.log(arr.at(-1)); console.log(arr.at(-2));
1 / 5 / 4

Array.at() supports negative indexing. at(0) = first element = 1. at(-1) = last = 5. at(-2) = second from end = 4.

167basic

What is the output?

const map = new Map(); map.set('a', 1); map.set('b', 2); map.set('a', 3); console.log(map.size); console.log(map.get('a'));
2 / 3

Setting an existing key overwrites its value — it does not add a new entry. After three set calls with two distinct keys ('a' and 'b'), size is 2. map.get('a') returns the latest value: 3.

168basic

What is the output?

const str = 'hello'; const reversed = [...str].reverse().join(''); console.log(reversed);
'olleh'

Spreading a string gives individual characters: ['h','e','l','l','o']. reverse() mutates to ['o','l','l','e','h']. join('') reassembles to 'olleh'.

169medium

What is the output?

console.log(typeof class Foo {}); console.log(typeof function() {});
'function' / 'function'

Classes are syntactic sugar over constructor functions. typeof reports both a class and a function expression as 'function'. There is no 'class' type in JavaScript's type system.

170medium

What is the output?

const nums = [5, 3, 8, 1]; const sorted = [...nums].sort((a, b) => a - b); console.log(sorted); console.log(nums);
[1, 3, 5, 8] / [5, 3, 8, 1]

Spreading nums creates a shallow copy. sort() mutates only the copy. sorted is sorted ascending; nums remains the original [5, 3, 8, 1].

171medium

What is the output?

const obj = { a: 1 }; const key = 'a'; console.log(key in obj); console.log('toString' in obj);
true / true

The in operator checks own AND inherited properties. 'a' is an own property → true. 'toString' is inherited from Object.prototype → also true. Use hasOwnProperty to check only own properties.

172medium

What is the output?

let x = 10; function show() { console.log(x); } function change() { let x = 20; show(); } change();
10

JavaScript uses lexical scoping. show() was defined in the global scope where x = 10. Even though it is called from inside change() (where let x = 20), show() always sees its own lexical scope's x, which is the global 10.

173basic

What is the output?

const obj = { a: 1, b: 2 }; const { a, ...rest } = obj; console.log(a); console.log(rest);
1 / { b: 2 }

Object rest in destructuring collects all remaining own enumerable properties not explicitly destructured. a gets 1; rest gets { b: 2 }.

174advanced

What is the output?

const add = new Function('a', 'b', 'return a + b'); console.log(add(2, 3)); console.log(typeof add);
5 / 'function'

new Function() creates a function from a string of source code at runtime. add(2, 3) returns 5. typeof any function is 'function'.

175advanced

What is the output?

console.log(1 < 2 < 3); console.log(3 > 2 > 1);
true / false

Comparisons evaluate left to right. 1 < 2 = true, then true < 3 = 1 < 3 = true. 3 > 2 = true, then true > 1 = 1 > 1 = false.

176advanced

What is the output?

const obj = {}; obj.__proto__.hello = 'world'; const obj2 = {}; console.log(obj2.hello);
'world'

obj.__proto__ is Object.prototype — the prototype shared by all plain objects. Adding hello to it makes it available on every plain object, including obj2. This is prototype pollution — a common security concern.

177medium

What is the output?

const arr = Array.from({ length: 3 }, (_, i) => i * 2); console.log(arr);
[0, 2, 4]

Array.from({ length: 3 }, mapFn) creates an array of 3 elements. The map function receives (value, index) — value is undefined since the object has no numeric keys, index is 0, 1, 2. _ * 2 gives 0, 2, 4.

178medium

What is the output?

const p = new Promise((resolve) => { console.log('executor'); resolve('done'); }); console.log('after');
'executor' / 'after'

The Promise executor function runs synchronously when the Promise is constructed. 'executor' logs first, then resolve('done') is called (but .then() was never attached so nothing else logs), then 'after' logs.

179medium

What is the output?

function* range(start, end) { for (let i = start; i <= end; i++) { yield i; } } console.log([...range(1, 4)]);
[1, 2, 3, 4]

Generator objects are iterable. Spreading a generator collects all its yielded values. range(1, 4) yields 1, 2, 3, 4 (i <= end), so the result is [1, 2, 3, 4].

180advanced

What is the output?

const obj = { a: 1 }; const handler = { set(target, key, value) { if (typeof value !== 'number') throw new TypeError('Numbers only'); return Reflect.set(target, key, value); } }; const p = new Proxy(obj, handler); p.a = 99; console.log(p.a); try { p.a = 'x'; } catch(e) { console.log(e.message); }
99 / 'Numbers only'

The Proxy's set trap validates the value. p.a = 99 is a number, so Reflect.set applies it and p.a becomes 99. p.a = 'x' triggers the throw — caught and logged as 'Numbers only'.