Sök…
Anmärkningar
Vad är funktionell programmering?
Funktionell programmering eller FP är ett programmeringsparadigm som bygger på två huvudbegrepp obrukbarhet och statslöshet . Målet bakom FP är att göra din kod mer läsbar, återanvändbar och bärbar.
Vad är funktionell JavaScript
Det har varit en debatt om att kalla JavaScript ett funktionellt språk eller inte. Men vi kan absolut använda JavaScript som funktionellt på grund av dess natur:
- Har rena funktioner
- Har förstklassiga funktioner
- Har högre ordningsfunktion
- Det stöder immutability
- Har stängningar
- Rekursion och lista transforeringsmetoder (arrayer) som karta, reducera, filtrera ... osv
Exemplen bör täcka varje koncept i detaljer, och länkarna som anges här är bara för referens och bör tas bort när konceptet illustreras.
Acceptera funktioner som argument
function transform(fn, arr) {
let result = [];
for (let el of arr) {
result.push(fn(el)); // We push the result of the transformed item to result
}
return result;
}
console.log(transform(x => x * 2, [1,2,3,4])); // [2, 4, 6, 8]
Som ni ser accepterar vår transform
två parametrar, en funktion och en samling. Den kommer sedan att upprepa samlingen och skjuta värden till resultatet och kalla fn
på var och en av dem.
Ser bekant ut? Detta är mycket lik Array.prototype.map()
fungerar!
console.log([1, 2, 3, 4].map(x => x * 2)); // [2, 4, 6, 8]
Funktioner med högre ordning
I allmänhet kallas funktioner som fungerar på andra funktioner, antingen genom att ta dem som argument eller genom att returnera dem (eller båda), funktioner av högre ordning.
En funktion med högre ordning är en funktion som kan ta en annan funktion som ett argument. Du använder högre ordning när du skickar återuppringningar.
function iAmCallbackFunction() {
console.log("callback has been invoked");
}
function iAmJustFunction(callbackFn) {
// do some stuff ...
// invoke the callback function.
callbackFn();
}
// invoke your higher-order function with a callback function.
iAmJustFunction(iAmCallbackFunction);
En funktion med högre ordning är också en funktion som returnerar en annan funktion som resultat.
function iAmJustFunction() {
// do some stuff ...
// return a function.
return function iAmReturnedFunction() {
console.log("returned function has been invoked");
}
}
// invoke your higher-order function and its returned function.
iAmJustFunction()();
Identitet Monad
Detta är ett exempel på en implementering av identitetsmonaden i JavaScript och kan fungera som en utgångspunkt för att skapa andra monader.
Baserat på konferensen av Douglas Crockford om monader och gonader
Att använda denna metod att återanvända dina funktioner kommer att bli enklare på grund av den flexibilitet som denna monad ger, och sammansättning mardrömmar:
f(g(h(i(j(k(value), j1), i2), h1, h2), g1, g2), f1, f2)
läsbar, fin och ren:
identityMonad(value)
.bind(k)
.bind(j, j1, j2)
.bind(i, i2)
.bind(h, h1, h2)
.bind(g, g1, g2)
.bind(f, f1, f2);
function identityMonad(value) {
var monad = Object.create(null);
// func should return a monad
monad.bind = function (func, ...args) {
return func(value, ...args);
};
// whatever func does, we get our monad back
monad.call = function (func, ...args) {
func(value, ...args);
return identityMonad(value);
};
// func doesn't have to know anything about monads
monad.apply = function (func, ...args) {
return identityMonad(func(value, ...args));
};
// Get the value wrapped in this monad
monad.value = function () {
return value;
};
return monad;
};
Det fungerar med primitiva värden
var value = 'foo',
f = x => x + ' changed',
g = x => x + ' again';
identityMonad(value)
.apply(f)
.apply(g)
.bind(alert); // Alerts 'foo changed again'
Och också med föremål
var value = { foo: 'foo' },
f = x => identityMonad(Object.assign(x, { foo: 'bar' })),
g = x => Object.assign(x, { bar: 'foo' }),
h = x => console.log('foo: ' + x.foo + ', bar: ' + x.bar);
identityMonad(value)
.bind(f)
.apply(g)
.bind(h); // Logs 'foo: bar, bar: foo'
Låt oss prova allt:
var add = (x, ...args) => x + args.reduce((r, n) => r + n, 0),
multiply = (x, ...args) => x * args.reduce((r, n) => r * n, 1),
divideMonad = (x, ...args) => identityMonad(x / multiply(...args)),
log = x => console.log(x),
substract = (x, ...args) => x - add(...args);
identityMonad(100)
.apply(add, 10, 29, 13)
.apply(multiply, 2)
.bind(divideMonad, 2)
.apply(substract, 67, 34)
.apply(multiply, 1239)
.bind(divideMonad, 20, 54, 2)
.apply(Math.round)
.call(log); // Logs 29
Rena funktioner
En grundprincip för funktionell programmering är att den undviker att ändra applikationstillstånd (statslöshet) och variabler utanför dess omfattning (immutability).
Rena funktioner är funktioner som:
- med en given ingång, returnera alltid samma utgång
- de litar inte på någon variabel utanför deras omfattning
- de ändrar inte applikationstillståndet ( inga biverkningar )
Låt oss ta en titt på några exempel:
Rena funktioner får inte ändra någon variabel utanför deras omfattning
Felaktig funktion
let obj = { a: 0 }
const impure = (input) => {
// Modifies input.a
input.a = input.a + 1;
return input.a;
}
let b = impure(obj)
console.log(obj) // Logs { "a": 1 }
console.log(b) // Logs 1
Funktionen ändrade obj.a
värdet som ligger utanför dess omfattning.
Ren funktion
let obj = { a: 0 }
const pure = (input) => {
// Does not modify obj
let output = input.a + 1;
return output;
}
let b = pure(obj)
console.log(obj) // Logs { "a": 0 }
console.log(b) // Logs 1
Funktionen ändrade inte objektets obj
värden
Rena funktioner får inte förlita sig på variabler utanför deras omfattning
Felaktig funktion
let a = 1;
let impure = (input) => {
// Multiply with variable outside function scope
let output = input * a;
return output;
}
console.log(impure(2)) // Logs 2
a++; // a becomes equal to 2
console.log(impure(2)) // Logs 4
Denna orena funktion är beroende av variabel a
som definieras utanför dess omfattning. Så om a ändras kommer impure
funktionsresultat att vara annorlunda.
Ren funktion
let pure = (input) => {
let a = 1;
// Multiply with variable inside function scope
let output = input * a;
return output;
}
console.log(pure(2)) // Logs 2
Det pure
funktionsresultatet förlitar sig inte på någon variabel utanför dess omfattning.