Простое решение для объединения функций фильтра с Javascript

Я много-много раз использовал функцию .filter () для изменения содержимого данного массива, но недавно мне потребовалось разделить правила фильтрации на несколько функций, чтобы потом я мог легко их протестировать.

Я много гуглил и нашел множество решений, но ни одно из них не соответствовало простоте того, которое я придумал сам. В этой статье показано, как преобразовать простую функцию обратного вызова, которую мы передаем в .filter (), в несколько отдельных функций, каждая со своей уникальной логикой.

Давайте рассмотрим простое использование функции фильтра, когда мы хотим, чтобы в массиве оставалось только значение от 1 до 10.

Обычно, если мы хотим, чтобы наше значение удовлетворяло более чем 1 условиям, мы реализуем это так:

const arr = [1, 2, 3, 4, 5]
arr.filter(x => x > 1 && x < 10)

Однако, если мы хотим иметь отдельную функцию для проверки границ значения, которое мы разрешаем передавать, это будет выглядеть так:

const checkBoundaries = (value) => {
    if(value > 1 && value < 10) {
        return true;
    }
    return false;
}
arr.filter(checkBoundaries)

Что, если мы хотим поместить каждую проверку границ в отдельную функцию, чтобы сделать код более тестируемым и расширяемым в будущем? Затем нам нужно будет создать нашу собственную функцию combFilters.

Давайте сначала разделим наши проверки границ на 2 функции.

const upperBoundaryCheck = (value) => {
    if (value < 10) {
        return true;
    }
    return false;
};
const lowerBoundaryCheck = (value) => {
    if (value > 1) {
        return true;
    }
    return false;
};

Теперь мы можем создать функцию commonFilters, которая будет применять все правила фильтрации к входящему значению и будет возвращать единственное значение true или false.

В нашем случае мы хотим получить true, если все правила пройдут, иначе вернуть false. Вот как это будет реализовано:

const combineFilters = (...filters) => (item) => {
    return filters.map((filter) => filter(item)).every((x) => x === true);
};

CombineFilters - это каррированная функция, которая сначала вызывается с функциями фильтра в качестве аргументов, а второй раз вызывается методом .filter () с текущим значением.

arr.filter(combineFilters(upperBoundaryCheck, lowerBoundaryCheck));

Чтобы сделать его еще более читабельным, мы можем взять функцию комбинированных фильтров вне вызова метода .filter () следующим образом:

const combinedFilters = 
combineFilters(
upperBoundaryCheck,
lowerBoundaryCheck
);
arr.filter(combinedFilters)

Таким образом, мы можем добавить столько правил фильтрации, сколько захотим, чтобы объединить фильтры, не усложняя код для чтения, тестирования и сопровождения.

Смотрите полный код здесь: ССЫЛКА