You signed in with another tab or window.Reload to refresh your session.You signed out in another tab or window.Reload to refresh your session.You switched accounts on another tab or window.Reload to refresh your session.Dismiss alert
Functional programming is a way of writing clearner code through clever way of mutating, combinding, and using functions.
Arrow Functions (Fat Arrows)
Arrow functions create a concise expression that encapsulates a small piece of functionality. Additionally, arrows retain the scope of the caller inside the function eliminating the need ofself = this.
For example:
// const multiply = function(x, y) {// return x * y;// }// Can be rewritten as:// const multiply = (x, y) => { return x * y };// Since the function is a single expression return and braces are not needed:constmultiply=(x,y)=>x*y;console.log(multiply(5,10))// 50
Anonymous function is the function that was declared without any named identifier to refer to it.
For example:
// Normal functionfunctionsayHi(){alert('Hello world!');}sayHi();// Anonymous function assigned to sayHi variablevarsayHi=function(){alert('Hello World!');}// Use as an argument to other functionssetTimeout(function(){console.log('Hello World!');},1000);// Use as a closure(function(){alert('Hello World!');})();// Use as a closure with parameters(function(msg){alert(msg);}('Hello World!'));// An anonymous function can refer to itself via arguments.callee local variable, useful for recursive anonymous functionsconsole.log((function(n){return(1<n) ?arguments.callee(n-1)+n :1;})(10));// Instead of using arguments.callee, you can use named function expression insteadconsole.log((functionsum(n){return(n<=1) ?1 :sum(n-1)+n})(10));
Currying
Currying allows a function with multiple arguments to be translated into a sequence of functions. Curried functions can be tailored to match the signature of another function.
// Statement// function convertUnits(toUnit = 0, factor, offset) {// return function(input) {// return ((offset + input) * factor).toFixed(2).concat(toUnit)// }// }// Can be written as an expressionconstconvertUnits=(toUnit,factor,offset=0)=>input=>((offset+input)*factor).toFixed(2).concat(toUnit);constmilesToKm=convertUnits('km',1.60936,0);constpoundsToKg=convertUnits('kg',0.45460,0);constfarenheitToCelsius=convertUnits('degrees C',0.5556,-32);console.log(milesToKm(10));//"16.09 km"console.log(poundsToKg(2.5));//"1.14 kg"console.log(farenheitToCelsius(98));//"36.67 degrees C"constweightsInPounds=[5,15.4,9.8,110];// Without currying// const weightsInKg = weightsInPounds.map(x => convertUnits('kg', 0.45460, 0)(x));// With curryingconstweightsInKg=weightsInPounds.map(poundsToKg);console.log(weightsInKg);// 2.27kg, 7.00kg, 4.46kg, 50.01kg
Array Functions are the gateway to functional programming in JavaScript. These functions make short work of most imperative programming routines that work on arrays and collections.
[].every(fn)
Checks if all elements in an array pass a test.
[].some(fn) | [].includes(fn)
Checks if any of the elements in an array pass a test.
[].find(fn)
Returns the value of the first element in the array that passes a test.
[].filter(fn)
Creates an array filled with only the array elements that pass a test.
[].map(fn)
Creates a new array with the results of a function applied to every element in the array.
[].reduce(fn(accumulator, currentValue))
Executes a provided function for each value of the array (from left-to-right). Returns a single value, the accumulator.
[].sort(fn(a,b)) warning, mutates state!
Modifies an array by sorting the items within an array. An optional compare function can be used to customize sort behavior. Use the spread operator to avoid mutation. [...arr].sort()
[].reverse() warning, mutates state!
Reverses the order of the elements in an array. Use the spread operator to avoid mutation. [...arr] . reverse()
For example:
constnames=[{text:"Alpha",value:5},{text:"Beta",value:2},{text:"Gamma",value:4},];//Checks if all elements in an array pass a test.leteveryResult=names.every(x=>x.value>0);//true// Checks if any of the elements in an array pass a test.letsomeResult=names.some(x=>x.text==="Alpha");//true// Returns the value of the first element in the array that passes a test.letfindResult=names.find(x=>x.text==="Gamma");//{text: "Gamma", value: 4}// Creates an array filled with only the array elements that pass a test.letfilterResult=names.filter(x=>x.value>3);//[{text: "Alpha", value: 5}, {text: "Gamma", value: 4}]// Creates a new array with the results of a function applied to every element in the array.letmapResult=names.map(x=>({...x,value:x.value*10}));//[{text: "Alpha", value: 50}, {text: "Beta", value: 20}, {text: "Gamma", value: 40}];// Executes a provided function for each value of the array (from left-to-right). The returns a single value, the accumulator.letreduceResult=names.reduce((accumulator,currentValue)=>currentValue.value>accumulator.value ?currentValue :accumulator);// Get the largest object by value: {"text":"Alpha","value":5}// Modifies an array by sorting the items within an array. An optional compare function can be used to customize sort behavior. Use the spread operator to avoid mutation. [...arr].sort()letsortResult=[...names].sort((a,b)=>b.value-a.value);// reverses the order of the elements in an array. Use the spread operator to avoid mutation. [...arr].reverse()letreverseResult=[...names].reverse();// ResultsconstappDiv=document.getElementById('app');appDiv.innerHTML=`<p>every:${everyResult}</p><p>some:${someResult}</p><p>find:${JSON.stringify(findResult)}</p><p>filter:${JSON.stringify(filterResult)}</p><p>map:${JSON.stringify(mapResult)}</p><p>reduce:${JSON.stringify(reduceResult)}</p><p>reverse:${JSON.stringify(reverseResult)}</p><p>sort:${JSON.stringify(sortResult)}</p>`;
Method Chaining
Method chains allow a series of functions to operate in succession to reach a final result. Method chains allow function composition similar to a pipeline.
For example:
letcart=[{name:"Drink",price:3.12},{name:"Steak",price:45.15},{name:"Drink",price:11.01}];letdrinkTotal=cart.filter(x=>x.name==="Drink").map(x=>x.price).reduce((t,v)=>t+v).toFixed(2);console.log(`Total Drink Cost $${drinkTotal}`);// Total Drink Cost $14.13
A pipeline allows for easy function composition when performing multiple operations on a variable. Since JavaScript lacks a Pipeline operator, a design pattern can be used to accomplish the task.
constpipe=functions=>data=>{returnfunctions.reduce((value,func)=>func(value),data);};letcart=[3.12,45.15,11.01];constaddSalesTax=(total,taxRate)=>(total*taxRate)+total;consttally=orders=>pipe([x=>x.reduce((total,val)=>total+val),// sum the orderx=>addSalesTax(x,0.09),x=>`Order Total =${x.toFixed(2)}`// convert to text])(orders);console.log(tally(cart));// Order Total = 64.62