Lexical scope determines variable access based on where functions are defined, not where they're called. Affects closure behavior and variable resolution. Inner functions have access to outer scope variables. Consider scope chain performance and variable shadowing.
Regular functions: 'this' determined by call context. Arrow functions: lexical 'this' from enclosing scope. Method shorthand: bound to object. Consider bind/call/apply usage. Handle event handlers and callback contexts correctly.
Use closures to create private scope. Methods defined inside closure not accessible externally. Return public interface. Consider memory usage and encapsulation. Handle object composition and inheritance.
Generator functions create iterators using yield keyword. Enable lazy evaluation, infinite sequences. Handle memory-efficient iterations. Consider state management between yields. Implement proper error handling and cleanup.
Default parameters provide fallback values when arguments are undefined. Evaluated at call time. Can reference other parameters and use expressions. Consider undefined vs null behavior. Handle edge cases and parameter dependencies.
IIFEs execute immediately upon definition. Create private scope, avoid global namespace pollution. Common in module pattern implementation. Consider block scope alternatives in modern JavaScript. Handle parameter passing and return values.
Currying transforms multi-argument function into series of single-argument functions. Enables partial application, function composition. Implement using closures or libraries. Consider performance implications. Handle argument validation and error cases.
Functions that create and return other functions. Use closures for configuration, state. Handle parameter customization. Consider memory usage. Implement proper initialization and cleanup.
Functions that modify or enhance other functions. Add logging, memoization, validation. Maintain function properties and context. Consider chaining capabilities. Handle asynchronous decorators.
Throttle limits execution frequency. Debounce delays execution until pause in calls. Use closure for state. Handle timer cleanup. Consider immediate execution option. Implement proper error handling.
Return this from methods to enable chaining. Consider immutable alternatives. Handle errors in chain. Implement proper method dependencies. Consider builder pattern implementation.
Closures maintain access to their outer scope variables even after the outer function has returned. Used for data privacy, factory functions, and maintaining state. Common in event handlers and callbacks. Consider memory implications and potential memory leaks. Implement cleanup when necessary.
Function composition combines multiple functions into single function. Output of one function becomes input of another. Implement using reduce or specialized functions. Consider error handling and type consistency. Handle asynchronous composition.
Use tail call optimization where available. Implement iterative alternatives. Consider stack size limitations. Handle base cases properly. Implement memoization for performance. Consider trampoline pattern for deep recursion.
Pure functions always return same output for same input. No side effects, depend only on input arguments. Easier testing, debugging, and reasoning. Consider immutability and referential transparency. Handle external state appropriately.
Block scope limited to block (let/const). Function scope spans entire function (var). Affects variable accessibility and lifetime. Consider hosting behavior. Handle nested scopes and shadowing properly.
Modules create their own scope. Export/import controls accessibility. Consider module closure effects. Handle circular dependencies. Implement proper encapsulation strategies.
Function declarations are hoisted with their implementation. Function expressions are assigned to variables, not hoisted. Arrow functions provide lexical this binding. Each type has different scoping rules and use cases. Consider hoisting behavior, this binding, and arguments object availability.
Arguments object contains all passed function arguments. Not available in arrow functions. Array-like but not an array. Use rest parameters for modern alternative. Consider performance implications. Convert to array when needed using Array.from() or spread operator.
Rest parameters collect remaining arguments into array. Spread operator expands iterables into individual elements. More flexible than arguments object. Consider performance with large arrays. Handle type checking and validation.
Cache function results based on input arguments. Improve performance for expensive calculations. Consider cache size, key generation. Handle complex arguments, cleanup. Implement proper cache invalidation strategies.
Function declarations hoisted with implementation. Function expressions hoisted as variables. Affects code organization and accessibility. Consider temporal dead zone with let/const. Handle initialization order properly.
Check arguments length/type for different behaviors. Use default parameters, rest parameters. Consider function factories. Handle type checking and validation. Implement proper error handling for invalid cases.
Functions that take/return other functions. Enable function composition, callbacks, decorators. Common in functional programming patterns. Consider scope implications. Handle function context and arguments properly.
bind creates new function with fixed this. call/apply execute function immediately with specified this. Arrow functions maintain lexical this. Consider performance implications. Handle partial application cases.
Use arrow functions or bind for correct this context. Consider closure implications. Handle cleanup properly. Implement proper error handling. Consider performance with many handlers.