Here are 100 extremely tricky JavaScript questions covering various concepts that confuse developers:
HOISTING & TEMPORAL DEAD ZONE
1. What's the output?
console.log(a);
console.log(b);
console.log(c);
var a = 1;
let b = 2;
const c = 3;
2. What happens here?
function test() {
console.log(x);
if (false) {
var x = 1;
}
}
test();
3. What's logged?
console.log(typeof foo);
console.log(typeof bar);
var foo = function () {};
function bar() {}
CLOSURES & SCOPE
4. What's the output after 1 second?
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1000);
}
5. What's different here?
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1000);
}
6. What's the final value of counter?
function createCounter() {
var counter = 0;
return {
increment: () => ++counter,
decrement: () => --counter,
value: counter,
};
}
const c = createCounter();
c.increment();
console.log(c.value);
TYPE COERCION
7. What's the result?
console.log([] + []);
console.log([] + {});
console.log({} + []);
console.log({} + {});
8. What's logged?
console.log(0.1 + 0.2 === 0.3);
console.log(0.1 + 0.2);
console.log((0.1 * 10 + 0.2 * 10) / 10);
9. What's the output?
console.log(null == undefined);
console.log(null === undefined);
console.log(null == 0);
console.log(null >= 0);
console.log(null > 0);
WEIRD OPERATORS
10. What's the result?
console.log(+"");
console.log(+[]);
console.log(+{});
console.log(+null);
console.log(+undefined);
11. What happens?
const a = [1, 2, 3];
const b = [1, 2, 3];
console.log(a == b);
console.log(a === b);
console.log(a.toString() == b.toString());
12. What's logged?
console.log(1 < 2 < 3);
console.log(3 > 2 > 1);
FUNCTION WEIRDNESS
13. What's the output?
function foo() {
return {
bar: "hello",
};
}
function baz() {
return;
{
bar: "hello";
}
}
console.log(foo());
console.log(baz());
14. What happens?
(function () {
var a = (b = 3);
})();
console.log(typeof a);
console.log(typeof b);
15. What's the result?
console.log(foo);
var foo = 1;
function foo() {}
console.log(foo);
ARRAY WEIRDNESS
16. What's logged?
const arr = [1, 2, 3];
arr[10] = 99;
console.log(arr.length);
console.log(arr[5]);
17. What's the output?
console.log([1, 2, 3] + [4, 5, 6]);
console.log([1, 2, 3] - [4, 5, 6]);
18. What happens?
const arr = new Array(3);
console.log(arr);
console.log(arr.map((x) => "a"));
console.log(arr.fill().map((x) => "a"));
OBJECT PROPERTY WEIRDNESS
19. What's the output?
const obj = {};
obj[true] = "boolean";
obj[1] = "number";
obj["1"] = "string";
obj["true"] = "string boolean";
console.log(Object.keys(obj));
20. What happens?
const a = {};
const b = { key: "b" };
const c = { key: "c" };
a[b] = 123;
a[c] = 456;
console.log(a[b]);
PARSING & NUMBERS
21. What's logged?
console.log(parseInt("123abc"));
console.log(parseInt("abc123"));
console.log(parseInt(""));
console.log(parseInt("0x10"));
console.log(parseInt("10", 2));
22. What's the result?
console.log(Math.max());
console.log(Math.min());
console.log(Math.max() < Math.min());
23. What happens?
console.log((0.1).toFixed(20));
console.log(0.1 + 0.2 - 0.3);
console.log((0.1 + 0.2 - 0.3).toFixed(20));
REFERENCE VS VALUE
24. What's the final array?
function modify(arr) {
arr.push(4);
arr = [1, 2, 3, 4, 5];
arr.push(6);
}
const myArray = [1, 2, 3];
modify(myArray);
console.log(myArray);
25. What's logged?
let a = { x: 1 };
let b = a;
a.x = 2;
a = { x: 3 };
console.log(b.x);
PROTOTYPES
26. What's the output?
function Parent() {}
Parent.prototype.name = "parent";
function Child() {}
Child.prototype = new Parent();
const child = new Child();
console.log(child.name);
delete Child.prototype.name;
console.log(child.name);
27. What happens?
const obj = Object.create(null);
obj.toString = function () {
return "custom";
};
console.log(obj + "");
console.log(String(obj));
ASYNC WEIRDNESS
28. What's the execution order?
console.log("1");
setTimeout(() => console.log("2"), 0);
Promise.resolve().then(() => console.log("3"));
console.log("4");
29. What's logged?
async function test() {
console.log("start");
await Promise.resolve();
console.log("end");
}
console.log("before");
test();
console.log("after");
30. What happens?
Promise.resolve(1)
.then((x) => x + 1)
.then((x) => {
throw new Error("oops");
})
.then((x) => x + 1)
.catch((err) => 5)
.then((x) => x + 1)
.then(console.log);
DESTRUCTURING WEIRDNESS
31. What's the output?
const [a, b] = [1, 2, 3];
const [c, d, e, f] = [4, 5];
console.log(a, b, c, d, e, f);
32. What happens?
const obj = { a: 1, b: 2 };
const { a, b, c = 3, d } = obj;
console.log(a, b, c, d);
33. What's logged?
let a = 1,
b = 2;
[a, b] = [b, a];
console.log(a, b);
OPERATOR PRECEDENCE
34. What's the result?
console.log(2 + 3 + "4");
console.log("4" + 2 + 3);
console.log("4" + (2 + 3));
35. What happens?
console.log(false == "0");
console.log(false === "0");
console.log(0 == "");
console.log(0 === "");
VARIABLE DECLARATIONS
36. What's the output?
console.log(x);
var x = 5;
var x = 10;
console.log(x);
37. What happens?
function test() {
if (true) {
var a = 1;
let b = 2;
const c = 3;
}
console.log(a);
console.log(b);
console.log(c);
}
test();
REGEX WEIRDNESS
38. What's logged?
const regex = /test/g;
console.log(regex.test("test"));
console.log(regex.test("test"));
console.log(regex.test("test"));
39. What's the result?
console.log("123".match(/\d/));
console.log("123".match(/\d/g));
console.log("abc".match(/\d/g));
DATE WEIRDNESS
40. What's the output?
console.log(new Date("2023-02-30"));
console.log(new Date("2023/02/30"));
console.log(new Date(2023, 1, 30));
EVAL & WITH
41. What happens?
const code = "var x = 1; x + 1";
console.log(eval(code));
console.log(x);
42. What's logged?
function test() {
const obj = { a: 1 };
with (obj) {
var a = 2;
var b = 3;
}
console.log(obj.a);
console.log(b);
}
test();
ERROR HANDLING
43. What's the output?
try {
throw "string error";
} catch (e) {
console.log(e instanceof Error);
console.log(typeof e);
}
44. What happens?
function test() {
try {
return "try";
} catch (e) {
return "catch";
} finally {
return "finally";
}
}
console.log(test());
STRICT MODE
45. What's the difference?
function normal() {
x = 1;
return x;
}
function strict() {
"use strict";
x = 1;
return x;
}
console.log(normal());
// console.log(strict()); // What happens?
SYMBOL WEIRDNESS
46. What's logged?
const s1 = Symbol("test");
const s2 = Symbol("test");
console.log(s1 == s2);
console.log(s1 === s2);
console.log(s1.toString() === s2.toString());
47. What happens?
const obj = {};
const sym = Symbol("key");
obj[sym] = "symbol value";
obj["sym"] = "string value";
console.log(Object.keys(obj));
console.log(Object.getOwnPropertySymbols(obj));
PROXY WEIRDNESS
48. What's the output?
const target = { a: 1 };
const proxy = new Proxy(target, {
get: (target, prop) => target[prop] * 2,
});
console.log(proxy.a);
console.log(target.a);
target.a = 5;
console.log(proxy.a);
UNICODE & STRINGS
49. What's logged?
console.log("👨👩👧👦".length);
console.log([..."👨👩👧👦"].length);
console.log("café".length);
console.log("café".normalize().length);
MEMORY & PERFORMANCE
50. What's the final state?
let obj = { data: new Array(1000000).fill("data") };
let ref = obj;
obj = null;
console.log(typeof obj);
console.log(typeof ref);
// Is the array garbage collected?
Absolutely! Here are 50 more extremely tricky JavaScript questions covering even more edge cases and concepts:
GENERATOR WEIRDNESS
51. What's 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());
console.log(g.next());
52. What happens?
function* gen() {
const x = yield 1;
yield x + 10;
}
const g = gen();
console.log(g.next());
console.log(g.next(5));
console.log(g.next());
53. What's logged?
function* gen() {
try {
yield 1;
yield 2;
} catch (e) {
yield e;
}
}
const g = gen();
console.log(g.next());
console.log(g.throw("error"));
console.log(g.next());
ITERATION PROTOCOL
54. What's the result?
const obj = {
[Symbol.iterator]: function () {
let count = 0;
return {
next: () => ({ value: count++, done: count > 3 }),
};
},
};
console.log([...obj]);
55. What happens?
const arr = [1, 2, 3];
const iterator = arr[Symbol.iterator]();
arr.push(4);
console.log([...iterator]);
MICROTASKS & EVENT LOOP
56. What's the execution order?
console.log("1");
setTimeout(() => console.log("2"), 0);
Promise.resolve().then(() => {
console.log("3");
setTimeout(() => console.log("4"), 0);
});
queueMicrotask(() => console.log("5"));
console.log("6");
57. What's logged?
Promise.resolve().then(() => console.log("A"));
queueMicrotask(() => console.log("B"));
setTimeout(() => console.log("C"), 0);
queueMicrotask(() => console.log("D"));
Promise.resolve().then(() => console.log("E"));
WEAK REFERENCES
58. What happens over time?
let obj = { data: "important" };
const weakRef = new WeakRef(obj);
const finalizationRegistry = new FinalizationRegistry((heldValue) => {
console.log("Object was garbage collected:", heldValue);
});
finalizationRegistry.register(obj, "my-object");
obj = null;
// What happens to weakRef.deref()?
BIGINT WEIRDNESS
59. What's the output?
console.log(1n + 2);
console.log(1n == 1);
console.log(1n === 1);
console.log(typeof 1n);
console.log(1n > 0);
60. What happens?
const big = BigInt(Number.MAX_SAFE_INTEGER) + 1n;
console.log(big);
console.log(Number(big));
console.log(big.toString());
ARRAY BUFFER & TYPED ARRAYS
61. What's logged?
const buffer = new ArrayBuffer(8);
const view1 = new Int32Array(buffer);
const view2 = new Uint8Array(buffer);
view1[0] = 0x12345678;
console.log(view2[0], view2[1], view2[2], view2[3]);
62. What happens?
const arr = new Int8Array([128, 255, 300]);
console.log(arr);
console.log(arr[0] + arr[1] + arr[2]);
SHARED ARRAY BUFFER
63. What's the result?
const shared = new SharedArrayBuffer(4);
const view1 = new Int32Array(shared);
const view2 = new Int32Array(shared);
view1[0] = 42;
console.log(view2[0]);
Atomics.add(view1, 0, 8);
console.log(view2[0]);
PROPERTY DESCRIPTORS EDGE CASES
64. What's the output?
const obj = {};
Object.defineProperty(obj, "x", {
get: function () {
return this._x;
},
set: function (val) {
this._x = val * 2;
},
});
obj.x = 5;
console.log(obj.x);
console.log(obj._x);
console.log(Object.keys(obj));
65. What happens?
const obj = { a: 1 };
Object.defineProperty(obj, "b", { value: 2 });
obj.b = 3;
console.log(obj.b);
delete obj.b;
console.log(obj.b);
FROZEN/SEALED OBJECTS
66. What's logged?
const obj = { a: 1, b: { c: 2 } };
Object.freeze(obj);
obj.a = 3;
obj.b.c = 4;
console.log(obj.a);
console.log(obj.b.c);
67. What's the difference?
const obj1 = { a: 1 };
const obj2 = { a: 1 };
Object.seal(obj1);
Object.freeze(obj2);
obj1.a = 2;
obj2.a = 2;
obj1.b = 3;
obj2.b = 3;
console.log(obj1);
console.log(obj2);
MODULE BEHAVIOR
68. What happens with circular imports?
// file a.js
import { b } from "./b.js";
export const a = "a";
console.log("a.js:", b);
// file b.js
import { a } from "./a.js";
export const b = "b";
console.log("b.js:", a);
69. What's the execution order?
console.log("before import");
import("./module.js").then((m) => console.log("dynamic import:", m));
console.log("after import");
TEMPLATE LITERAL EDGE CASES
70. What's the output?
function tag(strings, ...values) {
console.log(strings);
console.log(values);
return "result";
}
const x = 1,
y = 2;
console.log(tag`a${x}b${y}c`);
71. What happens?
const template = (strings, ...keys) => {
return (values) => {
const result = [strings[0]];
keys.forEach((key, i) => {
result.push(values[key], strings[i + 1]);
});
return result.join("");
};
};
const t = template`Hello ${"name"}!`;
console.log(t({ name: "World" }));
REFLECT API WEIRDNESS
72. What's the result?
const obj = { a: 1 };
console.log(Reflect.has(obj, "a"));
console.log(Reflect.has(obj, "toString"));
console.log(Reflect.ownKeys(obj));
console.log(Reflect.getPrototypeOf(obj) === Object.prototype);
73. What happens?
function test(a, b, c) {
return a + b + c;
}
console.log(Reflect.apply(test, null, [1, 2, 3]));
console.log(Reflect.construct(Array, [1, 2, 3]));
IMPORT MAPS & DYNAMIC IMPORTS
74. What's logged?
async function loadModule() {
try {
const module = await import("nonexistent-module");
console.log(module);
} catch (e) {
console.log("Error:", e.message);
return await import("./fallback.js");
}
}
OBSERVABLE PATTERN
75. What's the execution pattern?
class Observable {
constructor(subscriber) {
this.subscriber = subscriber;
}
subscribe(observer) {
return this.subscriber(observer);
}
}
const obs = new Observable((observer) => {
observer.next(1);
setTimeout(() => observer.next(2), 100);
return () => console.log("unsubscribed");
});
const subscription = obs.subscribe({
next: (x) => console.log(x),
});
PRIVATE FIELDS EDGE CASES
76. What happens?
class Test {
#private = "secret";
static check(obj) {
try {
return obj.#private;
} catch (e) {
return "no access";
}
}
}
const t1 = new Test();
const t2 = { "#private": "fake" };
console.log(Test.check(t1));
console.log(Test.check(t2));
77. What's the output?
class Parent {
#value = "parent";
getValue() {
return this.#value;
}
}
class Child extends Parent {
#value = "child";
getChildValue() {
return this.#value;
}
}
const child = new Child();
console.log(child.getValue());
console.log(child.getChildValue());
TOP-LEVEL AWAIT
78. What's the execution order?
console.log("start");
const data = await fetch("/api/data").catch(() => ({ json: () => ({}) }));
console.log("fetched");
const result = await data.json();
console.log("parsed", result);
OPTIONAL CHAINING EDGE CASES
79. What's logged?
const obj = null;
console.log(obj?.a?.b?.c);
console.log(obj?.[Symbol.iterator]?.());
console.log(obj?.method?.());
console.log(obj?.method?.());
80. What happens?
const obj = { a: null };
console.log(obj.a?.b);
console.log(obj.a?.b?.c);
console.log(obj.a?.["b"]);
console.log(obj.a?.b?.["c"]?.d);
NULLISH COALESCING
81. What's the output?
console.log(null ?? "default");
console.log(undefined ?? "default");
console.log(0 ?? "default");
console.log("" ?? "default");
console.log(false ?? "default");
82. What's the difference?
const a = 0,
b = null;
console.log(a || "default");
console.log(a ?? "default");
console.log(b || "default");
console.log(b ?? "default");
LOGICAL ASSIGNMENT
83. What's the final value?
let a = null;
let b = 0;
let c = "hello";
a ||= "default";
b ||= "default";
c ||= "default";
console.log(a, b, c);
84. What happens?
const obj = { x: null, y: 0 };
obj.x ??= "assigned";
obj.y ??= "assigned";
obj.z ??= "assigned";
console.log(obj);
NUMERIC SEPARATORS & LITERALS
85. What's the output?
console.log(1_000_000);
console.log(0b1010_1010);
console.log(0o755);
console.log(0xff_ec_de_5e);
console.log(1_000_000 === 1000000);
INTL API WEIRDNESS
86. What's logged?
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
});
console.log(formatter.format(1234.56));
console.log(formatter.format(-1234.56));
console.log(formatter.formatToParts(1234.56));
87. What happens with dates?
const date = new Date("2023-12-25");
const formatter = new Intl.DateTimeFormat("en-US", {
timeZone: "UTC",
year: "numeric",
month: "long",
day: "numeric",
});
console.log(formatter.format(date));
WEB APIS IN NODE/BROWSER
88. What's different?
console.log(typeof window);
console.log(typeof global);
console.log(typeof globalThis);
console.log(typeof self);
PERFORMANCE API
89. What's measured?
performance.mark("start");
for (let i = 0; i < 1000000; i++) {
Math.random();
}
performance.mark("end");
performance.measure("loop", "start", "end");
console.log(performance.getEntriesByName("loop"));
ERROR BOUNDARIES & STACK TRACES
90. What's in the stack?
function a() {
b();
}
function b() {
c();
}
function c() {
throw new Error("oops");
}
try {
a();
} catch (e) {
console.log(e.stack);
console.log(e.message);
console.log(e.name);
}
91. What's the output?
Error.stackTraceLimit = 2;
function deep1() {
deep2();
}
function deep2() {
deep3();
}
function deep3() {
deep4();
}
function deep4() {
throw new Error("deep");
}
try {
deep1();
} catch (e) {
console.log(e.stack.split("\n").length);
}
CUSTOM ELEMENTS
92. What happens?
class MyElement extends HTMLElement {
connectedCallback() {
this.innerHTML = "<p>Hello World</p>";
}
}
customElements.define("my-element", MyElement);
console.log(customElements.get("my-element"));
WORKER BEHAVIOR
93. What's the communication pattern?
const worker = new Worker('data:application/javascript,postMessage("hello")');
worker.onmessage = (e) => console.log("Received:", e.data);
worker.postMessage("test");
STREAMING & ASYNC ITERATION
94. What's the output pattern?
async function* asyncGenerator() {
yield 1;
await new Promise((r) => setTimeout(r, 100));
yield 2;
await new Promise((r) => setTimeout(r, 100));
yield 3;
}
for await (const value of asyncGenerator()) {
console.log(value);
}
95. What happens with async iteration?
const asyncIterable = {
async *[Symbol.asyncIterator]() {
yield "a";
yield "b";
yield "c";
},
};
Promise.all([...asyncIterable]); // What happens?
ABORT CONTROLLER
96. What's the behavior?
const controller = new AbortController();
const signal = controller.signal;
setTimeout(() => controller.abort(), 1000);
try {
await fetch("/api/data", { signal });
} catch (e) {
console.log(e.name);
console.log(signal.aborted);
}
STRUCTURED CLONING
97. What's cloned and what's not?
const original = {
date: new Date(),
regex: /test/g,
func: () => "hello",
symbol: Symbol("test"),
undefined: undefined,
map: new Map([["key", "value"]]),
};
const cloned = structuredClone(original);
console.log(cloned);
COMPRESSION STREAMS
98. What's the output?
const stream = new CompressionStream("gzip");
const writer = stream.writable.getWriter();
const reader = stream.readable.getReader();
writer.write(new TextEncoder().encode("Hello World"));
writer.close();
reader.read().then((result) => {
console.log(result.value); // Compressed bytes
});
SCHEDULER API
99. What's the execution order?
scheduler.postTask(() => console.log("high"), { priority: "user-blocking" });
scheduler.postTask(() => console.log("low"), { priority: "background" });
scheduler.postTask(() => console.log("normal"));
console.log("sync");
TEMPORAL API (PROPOSAL)
100. What's different?
// If Temporal was available
const date1 = new Date("2023-01-15T10:30:00");
const date2 = new Date("2023-01-15T10:30:00Z");
console.log(date1.getTime() === date2.getTime()); // What's the difference?
// vs Temporal (when available)
const temporal1 = Temporal.PlainDateTime.from("2023-01-15T10:30:00");
const temporal2 = Temporal.ZonedDateTime.from("2023-01-15T10:30:00Z");
Top comments (0)