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:

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.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow