Рассмотрим следующий пример:
const samples = ["foo", "bar"];
const excludeFoos = function(item) {
  return item !== "foo";
}
const foos = samples.filter(excludeFoos);Рассмотрим следующий пример:
const samples = ["foo", "bar"];
const excludeFoos = function(item) {
  return item !== "foo";
}
const foos = samples.filter(excludeFoos);Именование вещей
"Если у вас есть имя духа, у вас есть власть над ним". – Джеральд Джей Суссман
Можете ли вы придумать лучшее имя для вашей функции exclude? Я знаю что могу. Он известен как notEqual. Простое знание этого как своего истинного имени делает его гораздо более универсальным, когда дело касается решения проблем. "исключить" имеет смысл в контексте фильтрации массива, но почему-то это имеет меньшее значение, если мы хотим использовать функцию exclude в другом месте.
if (exclude(a,b))
  console.log("a and b are not equal")
Функциональное программирование состоит в том, чтобы сделать функции максимально возможными, так что, двигаясь вперед, давайте придерживаться
const notEqual = (x,y) => x !== y
Function.prototype.bind
Function.prototype.bind используется для привязки значений к параметрам функции. Он обычно используется, потому что он является родным, поскольку ECMAScript 5 – что означает, что вы можете достичь своей цели, не добавляя никаких дополнительных зависимостей или не внося никаких изменений в существующий код.
const notEqual = (x,y) => x !== y
const samples = ['foo', 'bar']
const foos = samples.filter(notEqual.bind(null, 'foo'))
console.log(foos) // ["bar"]Вы можете использовать bind() для создания новой функции с привязанными параметрами;
//you can replace the param with anything you like, null is for the context
var excludeFoos = exclude.bind(null,"foos")
const foos = samples.filter(excludeFoos);
С ES6:
const foos = samples.filter(x => exclude(x, "foos"));
другой вариант - использовать bind(), но мне трудно читать:
const foos = samples.filter(exclude.bind(null, "foos"))
вы хотите выполнить свою функцию следующим образом: -
const samples = ["foo", "bar"];
const exclude = function(s) {
  return item => item !== s;
}
const foos = samples.filter(exclude("foo"));
console.log(foos)Здесь один для вас:
Есть несколько ответов, которые говорят о карри и частичном приложении.
И это отличное направление.
Но как только вы действительно получите функции более высокого порядка, вы можете сделать этот материал действительно чистым и легким в работе.
const curry = (f, ...initialArgs) => (...extraArgs) => {
  const args = [...initialArgs, ...extraArgs];
  return args.length >= f.length ? f(...args) : curry(f, ...args);
};
Так что это значит? 
Он позволяет вам передать функцию и дает вам функцию. Пока вы не пройдете достаточно аргументов для запуска функции, она продолжит передавать вам другую функцию, которая ожидает больше аргументов.
Что хорошего в этом?
const multiply = curry((x, y) => x * y);
const double = multiply(2);
const triple = multiply(3);
double(2); // 4
triple(9); // 27
Теперь очень легко определить что-то вроде вашего теста.
const notEqual = curry((test, x) => test !== x);
// you could do it like this, to reuse `notFoo`
const notFoo = notEqual("foo");
samples.filter(notFoo);
// you could do it like this, if you don't need `notFoo`
samples.filter(notEqual("foo"));
Но подождите! Там больше!
const filter = curry((predicate, array) => array.filter(predicate));
const removeFoos = filter(notEqual("foo"));
removeFoos(samples);
removeFoos(items);
removeFoos(otherStuff);
Теперь у меня есть функция, которая отфильтровывает foos, и я могу просто передавать ее массивы всякий раз, когда мне кажется.
Последний на данный момент:
const compose = (...fs) => x => fs.reduceRight((x, f) => f(x), x);
Вместо записи
h(g(f(x)));
Compose позволяет мне писать
const hgf = compose(h, g, f);
hgf(x);
hgf(y);
hgf(z);
// it read from right to left
const tto = compose(three, two, one);
// or from bottom to top
const tsf = compose(
  third,
  second,
  first
);
// because it runs like
y = third(second(first(x)));
Итак, давайте попробуем что-то дикое...
// lib functions (Ramda would work fine)
const map = curry((transform, array) => array.map(transform));
const reduce = curry((summarize, seed, array) => 
  array.reduce(summarize, seed));
const flatMap = curry((transform, array) =>
  array.map(transform).reduce((a, b) => a.concat(b), []));
// business functions
const castToEmployee = personData => new Employee(personData);
const isWorking = ({ active }) => active;
const removeSuperiors = curry((user, employee) =>
  employee.role <= user.role);
const customEmployeeCriteria = (criteria, employee) => { /*...*/ };
const removeDuplicates = (arr, employee) =>
  arr.some(person => person.id === employee.id)
    ? arr
    : arr.concat(employee);
Код библиотеки
const performCustomSearch = searchCriteria => 
  filter(cutomEmployeeCriteria(searchCriteria));
const getAuthorizedEmployeeList = currentUser =>
  filter(removeSuperiors(currentUser));
const buildEmployees = compose(
  filter(isWorking),
  map(castToEmployee),
);
const cleanResults = compose(
  filter(removeBrokenItem),
  map(removePrivateMembers),
  reduce(removeDuplicates, []),
);
const handleEmployeeRequest = (currentUser, searchCriteria) => compose(
  cleanResults,
  performCustomSearch(searchCriteria),
  getAuthorizedEmployeeList(currentUser),
  buildEmployees
);
Код API
//(maybe /employees/?search={...}&token=123)
router.get("/employees", (req, res) => {
  PersonService.getAll()
    .then(handleEmployeeRequest(req.user, req.query.search))
    .then(filteredEmployees => res.json(filteredEmployees));
});
И все готово. 
Легко, как пирог.
Здесь другая версия с примитивной функцией curry:
const samples = ["foo", "bar"];
const exclude = function(item,str) {
  return item !== str;
}
function curry(func){
  return function(var1){
    return function(var2){
      return func(var1,var2); 
    };
  };
}
console.log(curry(exclude)('foo')('bar'));  // true
console.log(samples.filter(curry(exclude)('foo')));  // ["bar"]