More on this blog at github.com/zhuanyongxi…

Concept:

A side effect is a change in the state of the system, or an observable interaction with the outside world, during the calculation of the result.

The concept of pure functions above is strict, as is the concept of side effects. It is very demanding and, in a nutshell, any interaction with the function’s external environment is a side effect. In the sense of the term “side effect,” it’s more about “changing the state of the system.”

Some of the side effects listed in the tutorial:

  • Changing a file system
  • Insert records into the database
  • Send an HTTP request
  • Variable data
  • Print/log
  • Get user input
  • DOM query
  • Accessing system Status

If there were no side effects at all, then our code would simply run through and waste a little power, and nothing else would happen, so there would be no point in writing code. So, in JS, our goal is not to eliminate side effects completely, but to avoid side effects that should not occur.

In the JS native method, map is very functional, it will return a new array, not change the original array. The pop method, on the other hand, is bad because it changes the array itself after manipulating it.

So remember to make a deep copy when writing pure functions using those side-effects:

Case 1

const myPop = x= > {
  let [...y] = x;
  return y.pop();
}
Copy the code

Using a fixed shared state or calling a pure function are not side effects, as shown in the following example:

Case 2

const a = 5;
function A(b) {
  return a + b;
}
A(5);
Copy the code

Examples of calling a pure function:

Example 3

function foo(x) {
  return bar(x);
}

function bar(y) {
  return y + 1;
}

foo(1);
Copy the code

Although it is not a side effect, it is more recommended to pass the function bar as an argument, so that it is decoupled and easier to use:

Example 4

function foo(fn, x) {
  return fn(x);
}

function bar(y) {
  return y + 1;
}

foo(bar, 1);
Copy the code

It will be more refreshing and convenient if you use the currified way:

Case 5

function foo(fn) {
  return function(x) {
    returnfn(x); }}function bar(y) {
  return y + 1;
}

foo(bar)(1);
Copy the code

One aspect of this example that still makes us uneasy is that the bar may be modified. Such as:

Case 6

function foo(fn, x) {
  return fn(x);
}

function bar(y) {
  return y + 1;
}
bar = undefined;
foo(bar, 1);
Copy the code

Of course, it’s very rare for our brain to cramp and write bar = undefined in the global scope to make our system go wrong, more likely in a function that has side effects. That’s why we want to avoid side effects. This situation will be improved in ES6, for example:

Example 7

const foo = function(fn, x) {
  return fn(x);
}

const bar = function(y) {
  return y + 1;
}
bar = undefined;	// error
foo(bar, 1);
Copy the code

I recommend using const mode, which is more secure, even if the error can be quickly located.

Note:

  • Note 1: If you go further, functions also have a way of delaying execution (IO containers) to make these operations pure for some of the side effects listed above.

References:

  • JS functional programming guide
  • Functional-Light JavaScript