Concepts of functional programming in JavaScript are increasingly more popular. One of the basic concepts relates to pure functions and side effects but maybe it will surprise you that it is connected to some best practices already available in object-oriented programming.
If you need to refresh basic nomenclature, please find 6 fundamental terms in functional JavaScript.
A pure function is a function in which output depends only on its input without side effects.
const **myFunction** = **input** => **input** + 1;
That means that if you run the same function a hundred times in different places of the system it will always produce the same predictable output.
Side effects are anything outside of the function that either influences it or is influenced by it.
let **state** = 0; const **yourFunction** = () => **state** = **state** + 1;
In the above code, you can see that yourFunction
depends on the variable state
and also changes its value on every run, that is a side effect. Without knowing the current value of state,
you are not able to predict the output of yourFunction.
Because you don’t know whether other functions are also working with the same variable, you are potentially affecting them as well.
The change of the variable state
is called mutation. JavaScript has the keyword let
to indicate mutablevariables and const
to indicate immutable variables. In functional programming, variables are always immutable(you can’t change their value) which is possible because you won’t have the need to mutate anything.
Everything you need to know about a pure function, you can learn from its input and output:
**myFunction** :: **number** -> **number** **addOne** :: **a** -> **a** + 1 **addOne**(1) // 2
Commonly your function calls a function from a framework to realize its purpose. Inversion of control means that a framework is calling your function to execute custom purpose.
Dependency injection is a type of inversion of control. Dependency is an external code that your function is dependent on, and injection is the act of providing it to your function.
We can explain these on code similar to the one we already introduced:
import **Database** from 'database-stuff'; class **YourClass** { **constructor** () { this.**database** = new **Database**(); } **yourFunction** () { this.**database**.**query**(); } }
You can see that are importing Database
package for handling database queries and that library is then used in YourClass
to query a database.
Now let’s do the same applying dependency injection:
class **MyClass** { **constructor** (database) { this.**database** = database; } **myFunction** () { return this.**database**.**query**(); } }
You can see that I am not importing anything and instead myClass
is expecting a framework to provide its constructor with a database object which I am using in myFunction
.
My post Making testable JavaScript code shows examples of code showing some additional challenges of state management with proposed solutions.
If you are interested to learn more about the differences between imperative (represented here by object-oriented code) and declarative (represented here by functional code) programming, find my post Imperative versus declarative code… what’s the difference?
You have probably already noticed that pure functions are functions that receive all their dependencies as their arguments and apply inversion of control by expecting to be consumed by a framework.
From that perspective, pure functions view the world as a transformation of inputs into outputs. A server is a pure function that receives URL and transforms that URL into HTML.
Real applications, of course, tend to be dependent on databases, a number of external APIs, or their sole purpose is the creation of side effects like DOM manipulations. The idea is to apply inversion of control and abstract from side effects in your code where possible to use a framework to manage integration and execution of side effects.
If you look at it from testing perspective then pure functions represent code ideal for unit testing and your control code executing side effects is ideal to be covered by integration tests. You are trying to separate business logic from state management and integrations by decoupling the execution of a task from its implementation.
I should also mention that when I was speaking of a framework in connection to pure functions, I should have been using the term monad. Monads are the way how functional programmer handles execution of side effects. If you are not familiar with monads, just imagine them as wrappers around values allowing them to be transformed and passed around with lazy execution.
In modern JavaScript frameworks like React or Angular, the principles of inversion of control and functional programming are applied.
In React you have the option to use pure functions to create your components. You can use Redux to create abstraction from state management and Redux-Observable to handle server request side effects as monads.
If your function receives an input and based on it always outputs the same data then it is pure and behaves in a predictable manner. If the function, however, manipulates DOM directly instead of just outputting data then it is impure because direct DOM manipulation is impure and as we can’t predict DOM state from the function we can’t get always predictable results.
Pure functions are a great method of decoupling the execution of a task from its implementation. It allows you to divide your concerns better in your architecture and think more of where your code can break or create undesirable side effects.
Originally published by Martin Novák at https://medium.com
☞ The Complete JavaScript Course 2019: Build Real Projects!
☞ Become a JavaScript developer - Learn (React, Node,Angular)
☞ JavaScript: Understanding the Weird Parts
☞ Vue JS 2 - The Complete Guide (incl. Vue Router & Vuex)
☞ The Full JavaScript & ES6 Tutorial - (including ES7 & React)
☞ JavaScript - Step By Step Guide For Beginners
☞ MERN Stack Front To Back: Full Stack React, Redux & Node.js
☞ Visual Studio Code Settings and Extensions for Faster JavaScript Development
☞ Vue.js Authentication System with Node.js Backend
#javascript