JavaScript Functional Programming

JavaScript is a programming language that supports functional programming, offering a rich set of functional programming features including higher-order functions, closures, pure functions, immutability, and currying.

Here are the commonly used functional programming features in JavaScript:

  1. Higher-Order Functions: A higher-order function is a function that accepts one or more functions as arguments, or returns a function as its result. They can be used to implement function composition, modularization, and abstraction. For example, array methods like map, filter, and reduce are all higher-order functions.

  2. Closures: A closure is a function that can access and operate on variables from its outer scope. It can be used to implement private variables and functions, currying, etc. For example, the counter function in the following code is a closure:

    function counter() {
      let count = 0;
      return function() {
        return ++count;
      }
    }
    const increment = counter();
    console.log(increment()); // 1
    console.log(increment()); // 2
    
  3. Pure Functions: A pure function is a function that always returns the same output for the same input and has no side effects (i.e., it does not modify external state). Pure functions ensure code testability, maintainability, and reusability. For example, the add function in the following code is a pure function:

    function add(a, b) {
      return a + b;
    }
    
  4. Immutability: Immutability refers to the fact that data cannot be modified once it has been created. Immutability can avoid race conditions when accessing data concurrently and simplify code logic and debugging. For example, the concat method in the following code returns a new array instead of modifying the original array:

    const arr1 = [1, 2, 3];
    const arr2 = arr1.concat(4);
    console.log(arr1); // [1, 2, 3]
    console.log(arr2); // [1, 2, 3, 4]
    
  5. Currying: Currying is the process of converting a function that accepts multiple arguments into a series of functions that each accept a single argument. Currying makes function composition and reuse more flexible and convenient. For example, the curry function in the following code can convert a function that accepts multiple arguments into a curried function:

    function curry(fn) {
      return function curried(...args) {
        if (args.length >= fn.length) {
          return fn.apply(this, args);
        } else {
          return function(...args2) {
            return curried.apply(this, args.concat(args2));
          };
        }
      };
    }
    const add = (a, b, c) => a + b + c;
    const curriedAdd = curry(add);
    console.log(curriedAdd(1, 2, 3)); // 6
    console.log(curriedAdd(1)(2, 3)); // 6
    console.log(curriedAdd(1)(2)(3)); // 6
    

The above are the commonly used functional programming features in JavaScript. They allow us to write code that is more concise, readable, maintainable, and efficient.