Functions
Core functions — first-class and higher-order functions, closures, this-binding, arrow functions, and call/apply/bind.
10 questions
JuniorTheoryVery commonHow do arrow functions differ from regular functions?
How do arrow functions differ from regular functions?
Arrow functions give a concise => syntax and, crucially, have no own this, arguments, super, or new.target — they inherit this lexically from the enclosing scope. They also cannot be used as constructors with new and have no prototype, so they suit callbacks but not object methods that need their own this.
Common mistakes
- ✗Believing an arrow function binds its own
thisdynamically like a regular function - ✗Trying to use an arrow function as a constructor with
newor expecting anargumentsobject
Follow-up questions
- →Why does an arrow used as an object method often log
undefinedforthis? - →How can you access variadic arguments inside an arrow function without
arguments?
MiddleTheoryVery commonWhat is a closure in JavaScript?
What is a closure in JavaScript?
A closure is a function bundled with the lexical environment it was created in, so it keeps access to that scope's variables even after the outer function has returned. This lets an inner function read and update outer variables, which is the basis for private state, function factories, and stateful callbacks.
Common mistakes
- ✗Thinking a closure copies outer variables instead of keeping a live reference to them
- ✗Believing variables become inaccessible once the outer function returns
Follow-up questions
- →How do closures let you implement a private counter with no exposed variable?
- →Do two closures from the same outer call share the same variables or get separate copies?
JuniorTheoryCommonWhat does it mean that functions are first-class in JavaScript?
What does it mean that functions are first-class in JavaScript?
Functions are values like any other: you can assign one to a variable, pass it as an argument, return it from another function, and store it in an array or object. This is what enables callbacks, higher-order functions, and event handlers like addEventListener('click', handler).
Common mistakes
- ✗Thinking first-class refers to execution priority or hoisting rather than functions being values
- ✗Believing functions cannot be returned from other functions or stored in data structures
Follow-up questions
- →How does first-class-function support make higher-order functions possible?
- →What is the difference between passing
handlerandhandler()toaddEventListener?
MiddleTheoryCommonWhat is the difference between call, apply, and bind?
What is the difference between call, apply, and bind?
All three set a function's this to a given object. call invokes it immediately with arguments listed individually; apply invokes it immediately but takes the arguments as a single array; bind does not invoke — it returns a new function with this (and any leading arguments) permanently fixed, to be called later.
Common mistakes
- ✗Thinking
bindinvokes the function immediately instead of returning a new one - ✗Swapping
callandapply—applytakes an array,calltakes a list
Follow-up questions
- →How does
bindenable partial application by pre-fixing leading arguments? - →How could you implement your own
bindusingapply?
MiddleTheoryCommonWhat is a higher-order function?
What is a higher-order function?
A higher-order function takes one or more functions as arguments, returns a function, or both. It relies on functions being first-class values. Array methods map, filter, and reduce are built-in examples that accept a callback, and a function factory that returns a configured function is the returning case.
Common mistakes
- ✗Confusing higher-order with recursive or nested functions
- ✗Thinking only functions that take a callback qualify, forgetting the returning-a-function case
Follow-up questions
- →Why does
mapqualify as higher-order while a plainforloop does not? - →How does a function factory demonstrate the returning-a-function case?
MiddleTheoryCommonHow is this resolved for a method, a standalone call, and an arrow?
How is this resolved for a method, a standalone call, and an arrow?
this is set by how a function is called, not where it is defined. Called as obj.method(), this is obj (implicit binding). Called standalone, this is the global object in sloppy mode or undefined in strict mode (default binding). An arrow has no own this and takes it lexically from the enclosing scope.
Common mistakes
- ✗Believing
thisis bound at definition rather than determined by the call site - ✗Expecting a method detached from its object to still keep its original
this
Follow-up questions
- →Why does passing
obj.methodas a callback often lose itsthis? - →What does
thisresolve to in a standalone call under strict versus sloppy mode?
JuniorTheoryOccasionalWhat is an IIFE and why was it used?
What is an IIFE and why was it used?
An IIFE (Immediately Invoked Function Expression) is a function that runs the moment it is defined, written as (function () { ... })(). Wrapping code in one creates a private scope: variables declared inside are not visible outside, which avoided polluting the global namespace before block-scoped let/const and ES modules made it largely unnecessary.
Common mistakes
- ✗Thinking an IIFE runs later or asynchronously rather than immediately at definition
- ✗Believing variables inside an IIFE leak to the global scope instead of staying private
Follow-up questions
- →Why must the function be wrapped in parentheses to form an IIFE?
- →How do
let/constand ES modules replace the scoping role of an IIFE?
MiddleTheoryOccasionalWhat does bind return, and what happens if you call the bound function with new?
What does bind return, and what happens if you call the bound function with new?
bind returns a brand-new function (an exotic bound function) that, when called, invokes the original with this permanently fixed to the bound value plus any pre-set leading arguments. It does not call the original immediately.
Common mistakes
- ✗Thinking
bindcalls the function immediately likecall - ✗Expecting the bound
thisto survive anewcall on the bound function - ✗Assuming pre-bound arguments are dropped when the bound function is constructed
Follow-up questions
- →Why does
newoverride thethisthatbindfixed? - →How does partial application with
bindkeep its pre-set arguments undernew?
SeniorTheoryOccasionalWhat are the main use cases and pitfalls of closures?
What are the main use cases and pitfalls of closures?
Closures power data privacy and the module pattern (an IIFE returning methods over private variables), function factories, and stateful callbacks. The classic pitfall is the loop-capture bug: a var loop shares one binding, so all callbacks see the final value, while let gives each iteration its own. Closures also retain captured variables, risking memory leaks if kept alive.
Common mistakes
- ✗Believing a
varloop gives each callback its own binding likeletdoes - ✗Assuming closures never retain memory, ignoring leaks from long-lived captured references
Follow-up questions
- →How exactly does swapping
varforletfix the loop-capture bug? - →How does the module pattern combine an
IIFEwith a closure to hide state?
SeniorTheoryOccasionalHow does this resolve across all the different call types?
How does this resolve across all the different call types?
There is a precedence: new makes this the fresh instance; explicit call/apply/bind (hard binding) sets it to the given object and wins over implicit; obj.method() makes this the receiver; a standalone call defaults to the global object or undefined in strict mode. An arrow ignores all of these — it has no own this and takes it lexically from where it was defined.
Common mistakes
- ✗Thinking implicit binding overrides an explicit
bindrather than the other way around - ✗Expecting an arrow function's
thisto change with the call site like a regular function
Follow-up questions
- →Why is
bindcalled hard binding, and can a latercalloverride it? - →What
thisdoes an arrow defined inside a constructor capture?