Common Function Bugs in JavaScript and How to Fix Them
Functions cause real bugs: lost this, early calls, shadowing, and closure traps. Here is how to fix each one.
Common Function Bugs in JavaScript and How to Fix Them
Functions are central to JS, and they cause a few recurring bugs. Here are the most common ones and how to fix them.
Bug 1: Lost this in a Callback
const obj = { name: "Kunal", greet() { console.log(this.name); }, }; setTimeout(obj.greet, 0); // undefined
setTimeout calls greet with this as the global object (or undefined in strict mode). The method reference detaches from obj.
Fix: bind, arrow, or wrapper.
setTimeout(obj.greet.bind(obj), 0); setTimeout(() => obj.greet(), 0);
Bug 2: Calling a Function Expression Too Early
doWork(); const doWork = () => { ... };
Throws ReferenceError (TDZ).
Fix: Declare before calling, or use a function declaration if hoisting is needed.
Bug 3: Closure Capturing the Loop Variable
for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 0); } // logs 3, 3, 3
var is function-scoped; all closures share one i.
Fix: Use let (fresh binding per iteration) or an IIFE.
Bug 4: Returning Undefined by Mistake
const makeUser = () => { name: "Kunal"; }; makeUser(); // undefined
The braces are treated as a block body, and name: "Kunal" is a label statement, not an object.
Fix: Wrap the object in parentheses for an expression body.
const makeUser = () => ({ name: "Kunal" });
Bug 5: Shadowing an Outer Variable
const name = "Kunal"; function greet() { console.log(name); // undefined var name = "Asha"; }
The inner var name is hoisted with undefined, shadowing the outer.
Fix: Use let with a distinct name.
Bug 6: Forgetting return in a Chain
function double(x) { x * 2; } double(5); // undefined
No return means undefined.
Fix: Add return.
Bug 7: Mutating Parameters Unexpectedly
function addItem(list) { list.push(4); return list; } const a = [1, 2, 3]; const b = addItem(a); console.log(a); // [1, 2, 3, 4] - a is mutated
Objects and arrays are passed by reference.
Fix: Copy before mutating.
const b = addItem([...a]);
The Takeaway
Common function bugs: lost this in callbacks, early calls to expressions, closure loop bugs, missing returns, shadowing, and reference mutation. Fixes: bind/arrows, declare-before-call, let in loops, return explicitly, distinct names, and copy before mutate.
Because the method is detached from obj when passed as a reference. setTimeout calls it with this as the global object (or undefined in strict mode). Fix it with .bind(obj), an arrow wrapper, or () => obj.method().
Use let instead of var so each iteration gets a fresh binding, or wrap the body in an IIFE that captures the current value of i as a parameter.
Because the braces are interpreted as a block body, and the object literal looks like a label statement. Wrapping the object in parentheses (n) => ({ x: 1 }) makes it an expression body that returns the object.
Because arrays are passed by reference. Mutating the parameter mutates the same object the caller holds. Copy the array ([...list]) before mutating if you want to preserve the original.
By spec. If a function has no return or a return with no expression, it returns undefined. Always add return explicitly when you need to send a value back to the caller.
Ready to master React completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.
Master React
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course.

