JavaScript was written in 10 days, and we've been debugging it for decades.
Microsoft, Amazon, Atlassian, Walmart, eBay, and several similar big tech companies test candidates' JavaScript knowledge with such quirky problems.
So if you are a frontend developerâ-âReact, Next.js, or maybe Node.js developer, you know JavaScript doesn't test syntax in interviews. It tests mental models.
If you don't understand how the engine thinks-hoisting, closures, the event loop, mutation-these questions will humble you very quickly.
Let's break 10 of them as a JS engine would.
Are you ready?
Cool, give me the output for âŠ
Problem 1: Modifying Array While Iterating (forEach +Â splice)
var aa = [1, 2, 3, 4, 5, 6];
aa.forEach(i => {
console.log(i);
if (i > 3) aa.splice(aa.indexOf(i), 1);
});
Mutation during iteration + how forEach handles index internally.
Output:
1
2
3
4
6
Explanation:
forEach moves forward using the internal index. When you remove 4, the array becomes [1,2,3,5,6]. Now the next index moves forwardâ-âbut since elements shifted left, 5 gets skipped. forEach iterates using an internal index and does not account for structural changes in the array during iteration.
When splice() removes an element, subsequent elements shift left, but the internal pointer still increments forward, causing elements to be skipped. This is why mutating an array while iterating over it often produces unexpected results.
You mutate the array while walking on it. Classic trap.Â
Dry Run:
Initial: [1,2,3,4,5,6]
i=1 â ok
i=2 â ok
i=3 â ok
i=4 â splice â [1,2,3,5,6]
Next internal index â skips 5
i=6 â splice â [1,2,3,5]
The engine doesn't rewind for your feelings.
JavaScript started as a browser toy and accidentally became the language that runs the internet.
Problem 2: Default Params + Destructuring
function getApp({ name = "Anonymous", age } = {}) {
console.log(name, age);
}
getApp({name:"Tech Monk Kapil",age:25});
getApp({age:25});
getApp();
Default parameters + destructuring + default object.
Output:
Tech Monk Kapil 25
Anonymous 25
Anonymous undefined
Explanation:
If argument missing â {} used.Â
If name missing â default applies.Â
If age is missing â undefined.Â
Destructuring + default object prevents a crash.
Dry Run:
Call 1 â name="john", age=25
Call 2 â name default, age=25
Call 3 â param defaults to {}, name default, age undefined
All these questions are curated and collected from my past interview experiences in last 10 years.
Problem 3: Immutable vs Mutating Copy
const obj = { id: 5, name: "Tech Monk Kapil" };
const updated = { ...obj, name: "Kapil Raghuwanshi" };
const updated1 = { ...obj };
updated1.name = "Mohan";
obj
updated
updated1
The spread operator makes a shallow copy.
Output:
{ id: 5, name: "Tech Monk Kapil" }
{ id: 5, name: "Kapil Raghuwanshi" }
{ id: 5, name: "Mohan" }
Explanation:
Spread creates a new object reference. But it's shallowâ-ânested objects would still mutate.
Read more about the shallow vs deep copy difference.
Simple right?
Cool, another one on similar lines then âŠ
Problem 4: Default Param + Rest Param
function getOutput(name = "Unknown", ...nums) {
console.log(name, nums);
}
getOutput("kapil", 10, 20, 30);
getOutput();
getOutput(undefined, 10, 20);
getOutput(null);
Default param triggers only on undefined.
Output:
kapil [10,20,30]
Unknown []
Unknown [10,20]
null []
Explanation:
Only undefined activates the default. null is considered a valid value.
Follow me on Medium and let's be connected on LinkedIn (@kapilraghuwanshi) and Twitter (@techygeeeky) for more such interesting tech articles.đ€
Problem 5: Promise.all +Â fetch
const GOOGLE = "https://www.google.com";
Promise.all([
fetch(GOOGLE).then(() => console.log("b")),
fetch(GOOGLE).then(() => console.log("c"))
]).then(() => console.log("after"));
Parallel promises + microtasks.
Output:
b
c
after
(or c then b - depends on network timing)
Explanation:
Promise.all executes promises in parallel and resolves only when all included promises resolve. The order of execution of individual .then() callbacks depends on when each promise settles, not the order they were declared. The final .then() runs after all promises are fulfilled. Both fetch calls fire simultaneously. Promise.all waits until both resolve. Then after runs.
Once you see JavaScript as a runtime engineâ-ânot a syntax languageâ-âinterviews become pattern recognition instead of panic mode.
Also, I have recently started creating tech content on my YouTube channel, just have a look at it TechMonkKapil, and subscribe if you like the content!đ€
Problem 6: Event Loop Madness
console.log("Script Start");
setTimeout(() => console.log("setTimeout"), 0);
async function check() {
console.log("Async Start");
await Promise.resolve();
console.log("Async End");
}
check();
new Promise((resolve) => {
console.log("Promise Executor");
resolve();
}).then(() => {
console.log("Promise Then");
});
console.log("Script End");
Call stack + microtask queue + macrotask queue.
Output:
Script Start
Async Start
Promise Executor
Script End
Async End
Promise Then
setTimeout
Explanation:
JavaScript executes synchronous code first, then processes all microtasks (like Promise.then and await), and finally handles macrotasks (like setTimeout). Microtasks are always completed before the next macrotask begins. This strict priority order determines the output sequence.
Order of priority:
- Synchronous code
- Microtasks (Promise, await)
- Macrotasks (setTimeout)
Event loop is deterministic. Chaos is only in our heads.
These questions are not about tricks. They're about understanding execution context, scope, mutation, and the event loop deeply.
Problem 7: map(parseInt) Trap
[10,10,10].map(parseInt)
[10,10,10].map(parseFloat)
map passes (value, index). parseInt(value, radix)
Output:
[10, NaN, 2]
[10,10,10]
Explanation:
parseInt("10", 0) â 10
parseInt("10", 1) â NaN
parseInt("10", 2) â 2
map passes three arguments to its callback: value, index, and array. Since parseInt expects the second argument to be a radix, the array index unintentionally becomes the radix value. This mismatch leads to unexpected results like NaN.
Index becomes radix. Interview classic
JavaScript distinguishes absence from intentional emptiness.
Problem 8: Function vs var Hoisting
console.log(typeof foo)
var foo
function foo(){}
Function hoisting wins over var.
Output:
"function"
Explanation:
Function declarations are hoisted first. var is hoisted, but without overwriting the function at that stage.
JavaScript didn't win because it was perfect; it won because it was everywhere.
The next one is very famous already, and 80% chances are there that you have faced or solved this already.Â
But still give it a try one more time
Problem 9: IIFE Closure with setTimeout
for (var i = 0; i < 5; i++) {
(function(i) {
setTimeout(() => {
console.log(i);
}, i * 2000);
})(i);
}
Closure + IIFE + var scope.
Output:
0
after 2 sec
1
after 2 sec
2
after 2 sec
3
after 2 sec
4
Explanation:
var is function-scoped, so without additional scoping, all loop iterations would share the same variable reference. Wrapping each iteration in an IIFE creates a new execution context and captures the current value in a closure. This preserves the expected behavior for asynchronous callbacks. IIFE creates a new scope per iteration. Without it â all would print 5.
Problem 10: Arrow Function and this
let person = {
name: 'Kapil',
hobbies: ['React', 'Langchain', 'Next.js'],
showHobbies: function() {
this.hobbies.forEach((hobby) => {
console.log(`${this.name} likes ${hobby}`);
});
}
};
person.showHobbies();
Arrow function inherits this.
Kapil likes React
Kapil likes Langchain
Kapil likes Next.js
Arrow functions do NOT bind their own this. They inherit from the parent scope (showHobbies). If normal function used â this would be undefined (or window).
That's all, folks, for this article. Hope it was fun!đ
Hope you learned something new today, at least one new concept. If yes, save it and share it with your colleagues.
Also, I have recently started creating tech content on my YouTube channel, just have a look at it TechMonkKapil, and subscribe if you like the content!đ€
Also, we are building a tech community on Telegram(Tech Monks) and Discord(Tech Monks). Join if you are looking to interact with like-minded folks.
Follow me on Medium and let's be connected on LinkedIn (@kapilraghuwanshi) and Twitter (@techygeeeky) for more such interesting tech articles.đ€
Write your suggestions and feedback in the comment section belowđđ»




Top comments (0)