Functional programming
The functional style in JavaScript rests on functions being first-class values: they can be composed, wrapped, and configured. At the base of everything is the pure function — predictable, with no side effects. From it grow composition, currying, partial application, and memoization.
The topic is dense with terms candidates mix up: currying versus partial application, compose versus pipe, mixins versus inheritance. Each layer below separates a pair of similar ideas by mechanics — not by a pretty definition. Arity (fn.length) stands apart, because currying and partial application rely on the parameter count.
Topic map
- Pure functions — deterministic output with no side effects, and why it is the base of the whole style.
- Function composition —
composeandpipe, combining functions into a pipeline, and their directions. - Currying — turning an n-ary function into a chain of unary ones, called as
f(1)(2)(3). - Partial application — fixing some arguments up front, and how it differs from currying.
- Function arity — the parameter count and what
fn.lengthactually counts. - Memoization — caching the result by arguments, the purity requirement, and the key pitfall.
- Mixins — copying methods via
Object.assigninstead of inheritance.
Common traps
| Mistake | Consequence |
|---|---|
| Calling a function that mutates an argument pure | Hidden side effects, non-reproducible tests |
| Confusing currying and partial application | A wrong answer to the classic interview question |
Swapping the direction of compose and pipe | The pipeline runs its steps in reverse order |
| Memoizing an impure function | The cache returns stale values |
| Keying objects naively in a cache | Distinct objects collide as [object Object] |
Expecting super after a mixin | Object.assign copies the method; there is no access to the original |
Interview relevance
The functional section is loved for its pairs of near-synonyms: the interviewer names two terms and expects you to separate them by mechanics. The answer "currying takes one argument per call, partial application fixes any number at once" is worth more than any textbook definition.
Typical checks:
- Defining purity through determinism and no side effects; examples of impure functions (
Date.now(),Math.random(), mutation). - The difference between currying and partial application; the role of the closure in both.
- The directions of
compose(right-to-left) andpipe(left-to-right). - When memoization pays off and when it only wastes memory; the cache-key pitfall.
Common wrong answer: "memoization speeds up any function". No — only a pure one whose result depends solely on its arguments, and only when the same inputs are expensive to recompute and actually recur. Otherwise the cache grows for no gain.