Один из самых любимых вопросов в интервью по JavaScript — «Чистые и нечистые функции». В Интернете доступно гораздо больше информации о функциональном программировании, и, вероятно, каждый разработчик знает, что такое чистая функция. Но возникают вопросы, зачем это нужно и действительно ли у нас есть практический пример этого.

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

/ Pure Function
const sumPure = (a, b) => {
  return a + b;
};

После вызова чистой функции он выдает результат ниже, что означает, что для каждого вызова функции он выдает одинаковый вывод.

sumPure(1, 1); // OutPut: 2
sumPure(1, 1); // OutPut: 2
sumPure(1, 1); // OutPut: 2

С другой стороны, функция Impure выдает разные выходные данные для каждого вызова функции.

// Impure Function

const sumImpure = (() => {
  let state = 0
  return (v) => {
    return state += v
  }
})();

sumImpure(1) // OutPut: 1
sumImpure(1) // OutPut: 2
sumImpure(1) // OutPut: 3

Ключевым выводом здесь является то, что даже если входные данные не меняются, нечистая функция может давать другой результат.

Чистая функция:

  • Может использоваться во многих экземплярах, не влияя на результаты вывода.
class Calculator {
  
  constructor(addFn) {
    this.addFn = addFn;
  }

  add(a, b) {
    return this.addFn(a, b);
  }
}

const c1 = new Calculator(add);
const c2 = new Calculator(add);

c1.add(1, 1); // OutPut: 2
c2.add(1, 1); // OutPut: 2

Вывод: если функция чистая и не имеет состояния, ее можно безопасно использовать совместно со многими экземплярами классов Calculator:

Нечистая функция:

  • Невозможно поделиться, потому что на внутреннее состояние можно повлиять извне.
const add = (() => {
  let state = 0;
  return (v) => {
    return state += v;
  }

})();


class Calculator {
  constructor(addFn) {
    this.addFn = addFn;
  }

  add(a, b) {
    return (this.addFn(a), this.addFn(b));
  }
}


const c1 = new Calculator(add);
const c2 = new Calculator(add);

c1.add(1, 1); // 2
c2.add(1, 1); // 4  <------ here we have `4` instead of `2`

Вывод: функция, которая не является чистой, не может использоваться совместно. Это связано с тем, что операции, выполняемые одним экземпляром калькулятора, будут влиять на состояние функции и, следовательно, на результат операций, выполняемых другим экземпляром калькулятора.

Практические варианты использования: