This is Part 8 of 10, a bonus practice article with 70 code-output challenges. Each challenge asks you to predict the result before revealing the answer and reasoning.
This Dev.to series has five core handbook articles plus five focused practice extras. Open the series page to move through the complete reading order:
Read the code, state the exact output or error, then explain the language rule. Do not run the snippet until you have committed to an answer. For React Native interviews, connect the JavaScript behavior to rendering, state updates, list handling, or the JavaScript thread when relevant.
this
async
/await
, and microtasksPredict the exact output before opening the answer.
let total = 0;
for (let i = 0; i < 3; i++) {
total += i;
}
console.log(total);
Why: The loop adds 0, 1, and 2.
var
callback loop Predict the exact output before opening the answer.
for (var i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i);
}, 0);
}
Why: var
creates one shared function-scoped binding.
let
callback loop Predict the exact output before opening the answer.
for (let i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i);
}, 0);
}
Why: let
creates a fresh binding for each iteration.
Predict the exact output before opening the answer.
const a = [1, 2];
const b = a;
b.push(3);
console.log(a.length);
Why: a
and b
reference the same array.
Predict the exact output before opening the answer.
const a = { user: { name: 'A' } };
const b = { ...a };
b.user.name = 'B';
console.log(a.user.name);
Why: Object spread copies only the outer object.
map
with a missing return Predict the exact output before opening the answer.
console.log(
[1, 2].map((x) => {
x * 2;
}),
);
Why: A block-bodied arrow function needs an explicit return
.
reduce
accumulator Predict the exact output before opening the answer.
console.log([1, 2, 3].reduce((sum, x) => sum + x, 0));
Why: The accumulator starts at zero and receives every value.
Predict the exact output before opening the answer.
console.log([10, 2, 1].sort());
Why: Without a comparator, values are sorted as strings.
Predict the exact output before opening the answer.
const a = [1, , 3];
console.log(a.length, 1 in a);
Why: The missing element is a hole, but array length remains three.
filter(Boolean)
Predict the exact output before opening the answer.
console.log([0, 1, '', 2, null].filter(Boolean));
Why: Boolean
removes every falsy value.
Predict the exact output before opening the answer.
console.log(0 == false, 0 === false);
Why: Loose equality coerces types; strict equality does not.
Predict the exact output before opening the answer.
console.log(0 || 10, 0 ?? 10);
Why: ||
falls back for falsy values, while ??
only falls back for nullish values.
Predict the exact output before opening the answer.
const user = null;
console.log(user?.profile?.name ?? 'Guest');
Why: Optional chaining returns undefined
, then ??
supplies the fallback.
Predict the exact output before opening the answer.
function make() {
let n = 0;
return () => ++n;
}
const next = make();
console.log(next(), next());
Why: The returned function retains its lexical n
binding.
this
Predict the exact output before opening the answer.
const user = {
name: 'A',
show() {
return (() => this.name)();
},
};
console.log(user.show());
Why: The arrow captures this
from the regular show
method.
Predict the exact output before opening the answer.
function show() {
return this.name;
}
const f = show.bind({ name: 'A' });
console.log(f());
Why: bind
creates a function with a fixed receiver.
Predict the exact output before opening the answer.
console.log('A');
setTimeout(() => console.log('B'), 0);
Promise.resolve().then(() => console.log('C'));
console.log('D');
Why: Synchronous work runs first, then microtasks, then timer tasks.
await
continuation Predict the exact output before opening the answer.
async function run() {
console.log(1);
await 0;
console.log(2);
}
run();
console.log(3);
Why: Code after await
continues in a microtask.
Predict the exact output before opening the answer.
Promise.reject('x')
.catch(() => 2)
.then(console.log);
Why: Returning from catch
fulfills the next promise.
map
result Predict the exact output before opening the answer.
const x = [1, 2].map(async (n) => n * 2);
console.log(x[0] instanceof Promise);
Why: An async callback always returns a Promise.
Predict the exact output before opening the answer.
const [a = 1, b = 2] = [undefined, null];
console.log(a, b);
Why: Defaults apply to undefined
, not null
.
Predict the exact output before opening the answer.
const o = {},
a = {},
b = {};
o[a] = 'one';
o[b] = 'two';
console.log(o[a]);
Why: Plain-object keys are coerced to the same string.
Predict the exact output before opening the answer.
const parent = { role: 'admin' };
const user = Object.create(parent);
console.log(user.role);
Why: Property lookup follows the prototype chain.
Predict the exact output before opening the answer.
const p = { x: 1 },
o = Object.create(p);
o.x = 2;
delete o.x;
console.log(o.x);
Why: Deleting the own property reveals the inherited one.
Object.freeze
is shallow Predict the exact output before opening the answer.
const o = Object.freeze({ x: { n: 1 } });
o.x.n = 2;
console.log(o.x.n);
Why: The nested object is not frozen.
Predict the exact output before opening the answer.
let count = 0;
const setCount = (v) => {
count = v;
};
setCount(count + 1);
setCount(count + 1);
console.log(count);
Why: This plain JavaScript model evaluates each update immediately; React batching differs, so discuss that distinction in an interview.
Predict the exact output before opening the answer.
let id;
const debounce = (f) => (x) => {
clearTimeout(id);
id = setTimeout(() => f(x), 0);
};
const f = debounce(console.log);
f(1);
f(2);
Why: The second call clears the first pending timer.
Promise.all
result order Predict the exact output before opening the answer.
Promise.all([Promise.resolve(2), 1]).then(console.log);
Why: Promise.all
preserves input order after resolving values.
Predict the exact output before opening the answer.
console.log(add(1, 2));
function add(a, b) {
return a + b;
}
Why: Function declarations are initialized during scope creation.
Predict the exact output before opening the answer.
const a = { x: undefined };
const b = JSON.parse(JSON.stringify(a));
console.log('x' in b);
Why: JSON serialization drops undefined
object properties.
These 40 additional challenges focus on the JavaScript traps frequently used in interview rounds: hoisting, scope, ==
, ===
, arrays, objects, coercion, and reference identity.
var
value Predict the exact output or error before opening the answer.
console.log(score);
var score = 10;
Why: var
declarations are initialized as undefined
before execution; the assignment happens later.
let
Predict the exact output or error before opening the answer.
console.log(score);
let score = 10;
Why: let
exists in the Temporal Dead Zone until its declaration runs.
Predict the exact output or error before opening the answer.
show();
function show() {
console.log('ready');
}
Why: Function declarations are initialized with their function body during scope creation.
Predict the exact output or error before opening the answer.
show();
var show = function () {
console.log('ready');
};
Why: Only show
is hoisted as undefined
; it is not callable before assignment.
var
shadows outer state Predict the exact output or error before opening the answer.
var value = 'outer';
function printValue() {
console.log(value);
var value = 'inner';
}
printValue();
Why: The local var value
is hoisted and shadows the outer variable.
const
Predict the exact output or error before opening the answer.
{
const token = 'secret';
}
console.log(typeof token);
Why: const
is block-scoped; typeof
on an undeclared name returns undefined
.
var
binding Predict the exact output or error before opening the answer.
function update(value) {
console.log(value);
var value = 'new';
console.log(value);
}
update('old');
Why: A parameter and a same-named var
share one function-scoped binding.
Predict the exact output or error before opening the answer.
let value = 1;
function read(value = value) {
return value;
}
console.log(read());
Why: The parameter binding shadows the outer name while it is still uninitialized.
Predict the exact output or error before opening the answer.
const user = new User();
class User {}
Why: Classes are not usable before their declaration is evaluated.
Predict the exact output or error before opening the answer.
const run = function internal() {
return typeof internal;
};
console.log(run());
console.log(typeof internal);
Why: The expression name is available inside the function body, not outside it.
var
leaks from an if block Predict the exact output or error before opening the answer.
if (true) {
var message = 'visible';
}
console.log(message);
Why: var
has function scope rather than block scope.
let
does not leak from an if block Predict the exact output or error before opening the answer.
if (true) {
let message = 'hidden';
}
console.log(typeof message);
Why: let
remains inside the block.
Predict the exact output or error before opening the answer.
let count = 1;
{
let count = 2;
console.log(count);
}
console.log(count);
Why: The inner block creates a separate binding.
Predict the exact output or error before opening the answer.
let status = '';
const readStatus = () => console.log(status);
status = 'ready';
readStatus();
Why: Closures retain the binding, not a copied old value.
for
loop let
scope Predict the exact output or error before opening the answer.
for (let index = 0; index < 1; index++) {}
console.log(typeof index);
Why: The loop initializer let
does not escape the loop.
for
loop var
scope Predict the exact output or error before opening the answer.
for (var index = 0; index < 1; index++) {}
console.log(index);
Why: The var
binding is available after the loop.
let
Predict the exact output or error before opening the answer.
let value = 1;
let value = 2;
Why: A lexical binding cannot be redeclared in the same scope.
const
Predict the exact output or error before opening the answer.
const value = 1;
value = 2;
Why: const
prevents rebinding after initialization.
Predict the exact output or error before opening the answer.
var name = 'first';
function read() {
console.log(name);
var name = 'second';
}
read();
Why: The function-local var name
shadows the outer value before its assignment.
Predict the exact output or error before opening the answer.
function getValue() {
return 1;
}
var getValue = 2;
console.log(typeof getValue);
Why: The later assignment replaces the function value at runtime.
Predict the exact output or error before opening the answer.
console.log([] === []);
Why: Each array literal creates a different object.
Predict the exact output or error before opening the answer.
console.log([] == false);
Why: The empty array becomes an empty string, then zero; false
also becomes zero.
Predict the exact output or error before opening the answer.
console.log([] == 0);
Why: Loose equality converts the empty array to an empty string and then to zero.
Predict the exact output or error before opening the answer.
console.log([] == '');
Why: An empty array converts to an empty string.
Predict the exact output or error before opening the answer.
console.log([0] == 0);
Why: [0]
converts to the string "0"
, then to numeric zero.
Predict the exact output or error before opening the answer.
console.log([1] == true);
Why: [1]
converts to "1"
; both sides then compare as numeric one.
Predict the exact output or error before opening the answer.
console.log([1, 2] == '1,2');
Why: Arrays convert to their comma-joined string representation for this comparison.
Predict the exact output or error before opening the answer.
console.log([] == {});
Why: The array becomes ""
while the object becomes "[object Object]"
.
Predict the exact output or error before opening the answer.
console.log({} === {});
Why: Object equality compares identity, not matching properties.
Predict the exact output or error before opening the answer.
console.log(null == undefined, null === undefined);
Why: Loose equality has a special null/undefined rule; strict equality requires identical types.
Predict the exact output or error before opening the answer.
console.log(null == 0);
Why: The null/undefined loose-equality exception does not include zero.
Predict the exact output or error before opening the answer.
console.log('' == 0, '' === 0);
Why: Loose equality coerces the empty string to zero; strict equality does not coerce.
Predict the exact output or error before opening the answer.
console.log(false == '0');
Why: Both operands coerce to numeric zero during loose equality.
NaN
equality Predict the exact output or error before opening the answer.
console.log(NaN === NaN, Object.is(NaN, NaN));
Why: NaN
is not equal to itself with ===
; Object.is
handles it specially.
Object.is
and signed zero Predict the exact output or error before opening the answer.
console.log(0 === -0, Object.is(0, -0));
Why: ===
treats signed zeroes as equal; Object.is
distinguishes them.
Predict the exact output or error before opening the answer.
console.log([null] == '');
Why: A one-item array containing null converts to an empty string.
Predict the exact output or error before opening the answer.
console.log([undefined] == '');
Why: A one-item array containing undefined also converts to an empty string.
Predict the exact output or error before opening the answer.
console.log(Boolean(new Boolean(false)));
Why: Wrapper objects are objects, and objects are truthy.
Predict the exact output or error before opening the answer.
console.log(Boolean({}), Boolean([]));
Why: All ordinary objects and arrays are truthy, including empty ones.
Predict the exact output or error before opening the answer.
console.log('5' === 5, Number('5') === 5);
Why: Strict equality compares both type and value; explicit conversion makes types match.
Revisit Parts 6 and 7 for larger output-based and coding practice sets, then return to the core handbook for architecture, system design, and behavioral preparation.