Lesson guide

Learning objectives

  • Explain the main purpose of Currying in JavaScript.
  • Identify the syntax, APIs, or concepts introduced in this lesson.
  • Use the examples to predict how JavaScript will behave before you run similar code.
  • Connect this topic to nearby lessons in Miscellaneous.

Real-world context

This lesson matters when you need to recognize where Currying fits into real JavaScript programs. is an advanced technique of working with functions.

Key ideas

  • Currying is part of the Miscellaneous chapter, so it builds on the surrounding concepts rather than standing alone.
  • Read each code example in two passes: first for the result, then for the rule that explains the result.
  • When a section compares similar features, focus on the condition that makes you choose one feature over another.

Key terms

  • Currying
  • Miscellaneous
  • JavaScript

Currying is an advanced technique of working with functions. It’s used not only in JavaScript, but in other languages as well.

Currying is a transformation of functions that translates a function from callable as f(a, b, c) into callable as f(a)(b)(c).

Currying doesn’t call a function. It just transforms it.

Let’s see an example first, to better understand what we’re talking about, and then practical applications.

We’ll create a helper function curry(f) that performs currying for a two-argument f. In other words, curry(f) for two-argument f(a, b) translates it into a function that runs as f(a)(b):

javascript
function curry(f) { // curry(f) does the currying transform
  return function(a) {
    return function(b) {
      return f(a, b);
    };
  };
}

// usage
function sum(a, b) {
  return a + b;
}

let curriedSum = curry(sum);

alert( curriedSum(1)(2) );

As you can see, the implementation is straightforward: it’s just two wrappers.

  • The result of curry(func) is a wrapper function(a).
  • When it is called like curriedSum(1), the argument is saved in the Lexical Environment, and a new wrapper is returned function(b).
  • Then this wrapper is called with 2 as an argument, and it passes the call to the original sum.

More advanced implementations of currying, such as _.curry from lodash library, return a wrapper that allows a function to be called both normally and partially:

javascript
function sum(a, b) {
  return a + b;
}

let curriedSum = _.curry(sum); // using _.curry from lodash library

alert( curriedSum(1, 2) ); // 3, still callable normally
alert( curriedSum(1)(2) ); // 3, called partially

Currying? What for?

To understand the benefits we need a worthy real-life example.

For instance, we have the logging function log(date, importance, message) that formats and outputs the information. In real projects such functions have many useful features like sending logs over the network, here we’ll just use alert:

javascript
function log(date, importance, message) {
  alert(`[${date.getHours()}:${date.getMinutes()}] [${importance}] ${message}`);
}

Let’s curry it!

javascript
log = _.curry(log);

After that log works normally:

javascript
log(new Date(), "DEBUG", "some debug"); // log(a, b, c)

…But also works in the curried form:

javascript
log(new Date())("DEBUG")("some debug"); // log(a)(b)(c)

Now we can easily make a convenience function for current logs:

javascript
// logNow will be the partial of log with fixed first argument
let logNow = log(new Date());

// use it
logNow("INFO", "message"); // [HH:mm] INFO message

Now logNow is log with fixed first argument, in other words “partially applied function” or “partial” for short.

We can go further and make a convenience function for current debug logs:

javascript
let debugNow = logNow("DEBUG");

debugNow("message"); // [HH:mm] DEBUG message

So:

  1. We didn’t lose anything after currying: log is still callable normally.
  2. We can easily generate partial functions such as for today’s logs.

Advanced curry implementation

In case you’d like to get in to the details, here’s the “advanced” curry implementation for multi-argument functions that we could use above.

It’s pretty short:

javascript
function curry(func) {

  return function curried(...args) {
    if (args.length >= func.length) {
      return func.apply(this, args);
    } else {
      return function(...args2) {
        return curried.apply(this, args.concat(args2));
      }
    }
  };

}

Usage examples:

javascript
function sum(a, b, c) {
  return a + b + c;
}

let curriedSum = curry(sum);

alert( curriedSum(1, 2, 3) ); // 6, still callable normally
alert( curriedSum(1)(2,3) ); // 6, currying of 1st arg
alert( curriedSum(1)(2)(3) ); // 6, full currying

The new curry may look complicated, but it’s actually easy to understand.

The result of curry(func) call is the wrapper curried that looks like this:

javascript
// func is the function to transform
function curried(...args) {
  if (args.length >= func.length) { // (1)
    return func.apply(this, args);
  } else {
    return function(...args2) { // (2)
      return curried.apply(this, args.concat(args2));
    }
  }
};

When we run it, there are two if execution branches:

  1. If passed args count is the same or more than the original function has in its definition (func.length) , then just pass the call to it using func.apply.
  2. Otherwise, get a partial: we don’t call func just yet. Instead, another wrapper is returned, that will re-apply curried providing previous arguments together with the new ones.

Then, if we call it, again, we’ll get either a new partial (if not enough arguments) or, finally, the result.

Fixed-length functions only

The currying requires the function to have a fixed number of arguments.

A function that uses rest parameters, such as f(...args), can’t be curried this way.

A little more than currying

By definition, currying should convert sum(a, b, c) into sum(a)(b)(c).

But most implementations of currying in JavaScript are advanced, as described: they also keep the function callable in the multi-argument variant.

Common mistakes

  • Skipping the small examples and then missing the exact rule that Currying depends on.
  • Copying code without changing one value at a time to see which part controls the result.
  • Treating similar-looking syntax or APIs as interchangeable before checking their edge cases.

Summary

Currying is a transform that makes f(a,b,c) callable as f(a)(b)(c). JavaScript implementations usually both keep the function callable normally and return the partial if the arguments count is not enough.

Currying allows us to easily get partials. As we’ve seen in the logging example, after currying the three argument universal function log(date, importance, message) gives us partials when called with one argument (like log(date)) or two arguments (like log(date, importance)).

Predict

Before running this currying check, predict the five output lines. It uses a multi-argument curry helper that supports normal calls, partial calls, and reusable logging helpers.

javascript
Reveal explanation

The output is [10:00] [INFO] ready, [10:00] [INFO] ready, [10:00] [DEBUG] step, 6, and 6. The helper calls the original function only after it has at least func.length arguments. Until then it returns partial functions that remember earlier arguments. logAtTen fixes the first argument, and debugAtTen fixes the first two. The same curry helper still allows grouped calls such as curriedSum(1, 2)(3), not only one argument at a time.

Try it

Add a rest parameter to sum, then predict why this curry helper can no longer know how many arguments it should wait for.

Practice

  • Rewrite one example from this lesson without looking at the original, then run it and compare the result.
  • Change one input, operator, method call, or option in a code sample and predict what will happen before running it.
  • Explain Currying in your own words as if you were reviewing it with another learner.

Keep learning

Continue with Reference Type when you are ready for the next lesson.