Functional Programming in JavaScript: Advanced Techniques

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction to Functional Programming at an Advanced Level

\n\n

Functional programming (FP) is a paradigm that treats computation as the evaluation of mathematical functions and avoids changing state and mutable data. In JavaScript, especially in the Node.js environment, FP is becoming increasingly popular due to its predictability, testability, and parallelism.

\n\n

If you have already mastered the basics of FP (pure functions, higher-order functions, map, filter, reduce), it's time to move to the next level. In this article, we will cover advanced concepts: currying, composition, monads, and working with immutable data.

\n\n

1. Currying and Partial Application

\n\n

What is Currying?

\n

Currying is the process of transforming a function that takes multiple arguments into a sequence of functions, each taking a single argument. This allows you to create specialized functions based on general ones.

\n\n
// Regular function\nconst add = (a, b, c) => a + b + c;\nconsole.log(add(1, 2, 3)); // 6\n\n// Curried version\nconst curriedAdd = a => b => c => a + b + c;\nconsole.log(curriedAdd(1)(2)(3)); // 6\n\n// Universal currying function\nconst curry = (fn) => {\n  const arity = fn.length;\n  const resolver = (...args) => {\n    if (args.length < arity) {\n      return (...nextArgs) => resolver(...args, ...nextArgs);\n    }\n    return fn(...args);\n  };\n  return resolver;\n};\n\nconst multiply = (a, b, c) => a * b * c;\nconst curriedMultiply = curry(multiply);\nconsole.log(curriedMultiply(2)(3)(4)); // 24\nconsole.log(curriedMultiply(2, 3)(4)); // 24
\n\n

Partial Application

\n

Partial application is fixing a portion of a function's arguments, creating a new function with fewer arguments. Unlike currying, partial application does not require a strict sequence of calls.

\n\n
const partial = (fn, ...presetArgs) => (...laterArgs) => fn(...presetArgs, ...laterArgs);\n\nconst greet = (greeting, name) => `${greeting}, ${name}!`;\nconst sayHello = partial(greet, 'Hello');\nconst sayHi = partial(greet, 'Hi');\n\nconsole.log(sayHello('Alice')); // Hello, Alice!\nconsole.log(sayHi('Bob'));     // Hi, Bob!
\n\n

2. Function Composition

\n\n

Advanced Composition

\n

Composition is the process of combining several functions to create a new function. In advanced FP, we use right-to-left composition (compose) and left-to-right composition (pipe).

\n\n
// Simple composition (right to left)\nconst compose = (...fns) => (value) => fns.reduceRight((acc, fn) => fn(acc), value);\n\n// Left-to-right composition (pipe)\nconst pipe = (...fns) => (value) => fns.reduce((acc, fn) => fn(acc), value);\n\n// Example: string processing\nconst trim = (str) => str.trim();\nconst toLowerCase = (str) => str.toLowerCase();\nconst capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);\nconst removeSpaces = (str) => str.replace(/\\s+/g, '-');\n\nconst slugify = compose(capitalize, toLowerCase, trim, removeSpaces);\n// Equivalent: removeSpaces(trim(toLowerCase(capitalize("  Hello World  "))))\n\nconsole.log(slugify('  Hello World  ')); // Hello-world
\n\n

Transducers

\n

Transducers are compositions of transformation functions that work with any iterable data structure. They allow combining multiple operations (e.g., map and filter) into a single pass.

\n\n
const transducer = (mapper, predicate) => (reducer) => (acc, value) => {\n  const mapped = mapper(value);\n  return predicate(mapped) ? reducer(acc, mapped) : acc;\n};\n\nconst double = (x) => x * 2;\nconst isEven = (x) => x % 2 === 0;\n\nconst processNumbers = transducer(double, isEven);\nconst sumReduc                

Blogs

Book Recommendations