Here's why you SHOULD be using currying

Currying is a technique that makes use of partial application to transform a function with multiple arguments into a sequence of functions, each with a single argument (aka single arity). The inner functions are closures, having access to their own scope and the scope of their outer functions, and in this way the transformed function essentially has the same behaviour.

For example:

function doSomething(arg1, arg2) {  
  return arg1 + arg2;
}

doSomething(2, 3); // => 5  

Becomes:

function doSomething(arg1) {  
  return function(arg2) {
    return arg1 + arg2;
  }
}

doSomething(2)(3); // => 5  

Or using some ES6 syntactic sugar:

const doSomething = arg1 => arg2 => (arg1 + arg2);

doSomething(2)(3); // => 5  

Nice, right?!

Why is this helpful?

The value offered by this may not be immediately obvious, but the value is there. Let's take a look, starting with point free syntax below.

Point free

In functional programming, point free syntax is a pattern that enables us to operate on data without explicitly referencing that data. This avoids time being spent defining and interpreting variable names, with syntax noise reduced. It also helps to keep functions generic.

To demonstrate this, first consider the map function in javascript. If we defined a function that take's a dataset and applies a transformation to it, using the built in map we would need to do something similar to the following, where data is specified as an argument to the function:

const setUserAgesTo10 = users => (  
  users.map(user => (Object.assign({}, user, { age: 10 })))
);

setUserAgesTo10([  
  { name: 'fred', age: 11 },
  { name: 'hannah', age: 12 },
]);
// => [{ name: 'fred', age: 10 }, { name: 'hannah', age: 10 }]

Now imagine we have the following curried implementation of map, with data provided during the final application.

const curriedMap = callbackFn => data => data.map(callbackFn);  

We can now define a point free implementation of the earlier function:

const setUserAgesTo10 = curriedMap(user => (  
  Object.assign({}, user, { age: 10 }))
);

setUserAgesTo10([  
  { name: 'fred', age: 11 },
  { name: 'hannah', age: 12 }
]);
// => [{ name: 'fred', age: 10 }, { name: 'hannah', age: 10 }]

As you can see, the data we are operating on, users, is no longer explicitly referenced. Neat huh?!

Functional composition

Another thing that currying enables is a clean syntax for functional composition using compose, a function available in many utility libraries. Functional composition is where we combine two or more functions to create a new function. By using curried functions with data last along with compose this can all be done point free, leading to some concise, easy to reason about code that is low in syntax noise. Perfect.

To demonstrate this, let's assume that uniq returns a new list with only one copy of each item in the original list, uppercase returns a new list with each item uppercased, sort returns a new list sorted alphabetically (ascending flag as the first parameter), and that all three are curried with data last. Originally, we have:

const names = [  
  'fred',
  'anna',
  'fred',
];
const ascendingSort = (sort(true));

const uniqueNames = uniq(names);  
const uniqueNamesUppercased = uppercase(uniqueNames);

ascendingSort(uniqueNamesUppercased);  
// => ['ANNA', 'FRED'];

With functional composition, this becomes:

const names = [  
  'fred',
  'anna',
  'fred',
];
const ascendingSort = (sort(true));

const uniqueUppercasedAndSorted = data => (  
  ascendingSort(
    uppercase(
      uniq(data)
    )
  )
);

uniqueUppercasedAndSorted(names);  
// => ['ANNA', 'FRED'];

Which thanks to currying, we can tidy up to become:

const names = [  
  'fred',
  'anna',
  'fred',
];
const ascendingSort = (sort(true));

const uniqueUppercasedAndSorted = compose(  
  ascendingSort,
  uppercase,
  uniq
);

uniqueUppercasedAndSorted(names);  
// => ['ANNA', 'FRED'];

Other benefits

Even if we opt not to take advantage of point free syntax and functional composition, there are still other benefits such as breaking function calls down into stages which can improve readability, and importantly can enable partially applied functions to be reused and repurposed to satisfy different needs.

In addition, currying provides one method of passing data into functions that the JavaScript runtime itself takes care of applying, such as event handler callbacks, via partial application. These callbacks are called implicitly when the event fires, with the JavaScript runtime providing the event data as an argument. This is showcased below:

const doSomething = (arg1, arg2) => e => {  
  console.log(arg1); // foo
  console.log(arg2); // bar
  console.log(e); // (the event object supplied by runtime)
}

document  
  .querySelector('body')
  .addEventListener('click', doSomething('foo', 'bar'));

To summarise...

Use currying to make your code more concise and readable with point free syntax and functional composition. Enable functions to be broken down, reused, then repurposed by currying the arguments. Utilise partial application to pass data to functions invoked by the JavaScript runtime such as event handler callbacks.