Functions, Closures, this, and Function Composition
Understand JavaScript functions as first-class values, closures, callback behavior, this binding, arrow functions, and advanced function patterns.
Functions Are First-Class Values
Functions can be assigned to variables, stored in objects, passed as arguments, returned from other functions, and dynamically constructed. This enables callbacks, higher-order functions, event handlers, middleware, composition, and functional programming techniques.
A function declaration and a function expression both create callable functions, but their declaration and initialization behavior differs.
function double(value) {
return value * 2;
}
function transform(value, operation) {
return operation(value);
}
console.log(transform(5, double));- Functions are values in JavaScript.
- Functions can be passed, returned, stored, and composed.
- Higher-order functions accept or return functions.
What is a higher-order function?
Closures: The Real Mental Model
A closure is created when a function retains access to variables from its lexical environment even after the outer function has finished executing. The important concept is not merely 'a function inside another function'; it is that the inner function retains access to the relevant lexical bindings.
Closures are used for private state, factories, memoization, callbacks, module patterns, and asynchronous code.
function createCounter() {
let count = 0;
return function increment() {
count += 1;
return count;
};
}
const counter = createCounter();
console.log(counter());
console.log(counter());- Closures preserve access to lexical bindings.
- Closures are useful for encapsulation and state.
- A closure retains reachable bindings, not necessarily every variable from the entire outer scope.
Why does `count` remain available after `createCounter()` returns?
How `this` Is Determined
Unlike lexical variables, this is generally determined by how a function is called. With a normal function, the call site matters. obj.method() gives this as obj. A standalone call in strict mode gives undefined. call, apply, and bind can explicitly control this.
Arrow functions are different: they do not create their own this; they capture this lexically from their surrounding context.
const user = {
name: 'Suriya',
greet() {
return this.name;
}
};
console.log(user.greet());
const greet = user.greet;
console.log(greet());thisis not simply the same thing as lexical scope.- Normal function this depends on invocation.
- Arrow functions capture this lexically.
What does an arrow function do with `this`?
call, apply, and bind
call invokes a function immediately with a specified this and individual arguments. apply does the same but receives arguments as an array-like collection. bind does not invoke immediately; it creates a new function with a permanently bound this and optionally pre-filled arguments.
These methods are especially useful when adapting APIs, creating callbacks, or working with methods that need an explicit receiver.
const user = {
name: 'Suriya'
};
function greet(prefix) {
return `${prefix}, ${this.name}`;
}
const greetUser = greet.bind(user, 'Hello');
console.log(greetUser());callinvokes immediately with individual arguments.applyinvokes immediately with an argument collection.bindreturns a new function for later invocation.
Which method returns a new function instead of immediately invoking the original function?
Map, Filter, Reduce, and Function Composition
Methods such as map, filter, and reduce are higher-order operations over collections. map transforms every element, filter selects elements, and reduce combines values into an accumulator. They are not merely shortcuts; they express different computational intentions.
Composition becomes especially useful when small pure functions are combined into larger transformations.
const numbers = [1, 2, 3, 4, 5, 6];
const result = numbers
.filter(n => n % 2 === 0)
.map(n => n * n)
.reduce((sum, n) => sum + n, 0);
console.log(result);- map transforms elements.
- filter selects elements.
- reduce models accumulation into one result.
Which method is most directly intended to transform every element into another value?