Currying Origins e o nome do matemático Haskell Curry (a linguagem de programação Haskell também recebe o nome dele).
A curry também é geralmente chamada de avaliação parcial. Seu significado é passar os parâmetros para uma função passo a passo. Depois que cada parâmetro é passado, aplique parcialmente parâmetros e retorne uma função mais específica para aceitar os parâmetros restantes. Várias camadas dessas funções parciais de parâmetro podem ser aninhadas no meio até que o resultado final seja retornado.
Portanto, o processo de currying é um processo de parâmetros gradualmente passantes, estreitando gradualmente o escopo da aplicação de funções e resolvendo gradualmente.
Currying uma função de soma
Após a avaliação passo a passo, vejamos um exemplo simples
var concat3words = function (a, b, c) {return a+b+c; }; var concat3wordScurrying = function (a) {return function (b) {return function (c) {return a+b+c; }; }; }; console.log (concat3words ("foo", "bar", "baza")); // Foo Bar Baza Console.log (Concat3WordScurrying ("Foo")); // [function] console.log (concat3wordscurrying ("foo") ("bar") ("baza")); // foo bar bazaComo você pode ver, o Concat3WordScurrying ("Foo") é uma função, cada chamada retorna uma nova função, que aceita outra chamada e, em seguida, retorna uma nova função até que o resultado seja finalmente retornado e a distribuição seja resolvida e progride a camada por camada. (PS: as características dos fechamentos são aproveitadas aqui)
Então agora vamos mais longe. Se exigirmos que mais de 3 parâmetros sejam passados, podemos passar o maior número possível de parâmetros e produzir o resultado quando os parâmetros não forem passados?
Primeiro, vamos ter uma implementação normal:
var add = function (itens) {return items.reduce (function (a, b) {return a+b}); }; console.log (add ([1,2,3,4]));Mas se você pedir para multiplicar cada número por 10 e adicione -o, então:
var add = function (itens, multi) {return items.map (function (item) {return item*multi;}). Reduce (function (a, b) {return a + b}); }; console.log (add ([1, 2, 3, 4], 10));Felizmente, existem mapa e redução de funções. Se seguirmos esse padrão, precisamos adicionar 1 a cada item e resumir -o, precisamos substituir as funções no mapa.
Vamos dar uma olhada na implementação de curryização:
var adder = function () {var _args = []; retornar function () {if (argumentos.Length === 0) {return _args.reduce (function (a, b) {return a + b;}); } [] .push.apply (_args, [] .slice.call (argumentos)); Retornar argumentos.callee; }}; var sum = adder (); console.log (soma); // Soma da função (100.200) (300); // O formato de chamada é flexível, um ou mais parâmetros podem ser inseridos por vez e suporta a chamada de cadeia para soma (400); console.log (sum ()); // 1000 (cálculo total)O Adder acima é uma função em forma de curry, que retorna uma nova função, e a nova função pode aceitar novos parâmetros em lotes, atrasando até o último cálculo.
Função geral de curry
Um curry mais típico encapsulará o último cálculo em uma função e depois passará essa função como um parâmetro para a função de curry, que é clara e flexível.
Por exemplo, multiplique cada termo por 10, podemos passar na função de processamento como um parâmetro:
var currying = function (fn) {var _args = []; retornar function () {if (argumentos.Length === 0) {return fn.apply (this, _args); } Array.prototype.push.apply (_args, [] .slice.call (argumentos)); Retornar argumentos.callee; }}; var multi = function () {var total = 0; for (var i = 0, c; c = argumentos [i ++];) {total+= c; } retornar total; }; var sum = currying (multi); soma (100.200) (300); soma (400); console.log (sum ()); // 1000 (é calculado apenas quando as chamadas em branco)Dessa maneira, soma = curry (multi), a chamada é muito clara e o efeito de uso também é brilhante. Por exemplo, para acumular vários valores, você pode usar vários valores como parâmetros soma (1,2,3) ou chamadas de cadeia de suporte, soma (1) (2) (3)
A fundação do currying
O código acima é na verdade uma função de alta ordem. Uma função de alta ordem refere-se a uma função que opera uma função. Ele recebe uma ou mais funções como parâmetros e retorna uma nova função. Além disso, as características do fechamento também são confiadas para salvar os parâmetros inseridos no processo intermediário. Agora mesmo:
As funções podem ser passadas como parâmetros
As funções podem ser usadas como valor de retorno da função
Encerramento
O papel do currínculo
Cálculo de atraso. O exemplo acima é relativamente baixo.
Multiplexação de parâmetros. Quando a mesma função é chamada várias vezes e os parâmetros passados são os mesmos, a função pode ser um bom candidato para o curry.
Crie funções dinamicamente. Isso pode ser gerado dinamicamente após os resultados do cálculo parcial; nessa base, uma nova função é gerada dinamicamente para processar os negócios subsequentes, omitindo assim cálculos repetidos. Ou você pode criar dinamicamente uma nova função aplicando parte do subconjunto de parâmetros a serem transmitidos para a função de chamada, que salva os parâmetros passados repetidamente (não necessariamente todas as vezes no futuro). Por exemplo, um método auxiliar para navegadores de eventos adicionar eventos:
var addEvent = function (el, tipo, fn, captura) {if (window.addeventListener) {el.addeventListener (type, function (e) {fn.call (el, e);}, captura); } else if (window.attachevent) {el.attachevent ("on" + tipo, function (e) {fn.call (el, e);}); }};Toda vez que você adiciona um evento, você deve executar se ... caso contrário .... De fato, em um navegador, você só precisa tomar uma decisão uma vez. Você pode gerar dinamicamente uma nova função com base no resultado após um julgamento, e não há necessidade de recalculá -la no futuro.
var addEvent = (function () {if (window.addeventListener) {retorna função (el, sype, fn, capture) {el.addeventListener (stype, function (e) {fn.call (el, e);}, (captura));};} else (wail.AtchEvent); el.attachevent ("on" + estype, função (e) {fn.call (el, e);});Este exemplo, após o primeiro julgamento de se ... else ..., parte do cálculo é concluído e uma nova função é criada dinamicamente para processar os parâmetros passados posteriormente. Esta é uma currylação típica.
O método function.prototype.bind também é um aplicativo de curry
Diferentemente do método de chamada/aplicação que é executado diretamente, o método de ligação define o primeiro parâmetro para o contexto da execução da função, e outros parâmetros são passados para o método de chamada por sua vez (o corpo da função em si não é executado, que pode ser considerado como retardado de execução), e as criadas dinamicamente retorna uma nova função, que está em conformidade com as características curry.
var foo = {x: 888}; var bar = function () {console.log (this.x); } .bind (foo); // barra de ligação (); // 888Abaixo está uma simulação de uma função de ligação. O TestBind cria e retorna uma nova função. Na nova função, a função que realmente deseja executar o negócio está vinculada ao contexto passada no parâmetro real e a execução é atrasada.
Function.prototype.testbind = function (escopo) {var fn = this; //// Isso aponta para uma função que chama o método TestBind, Return function () {return fn.apply (escopo); }}; var testBindBar = bar.testbind (foo); // liga foo para atrasar a execução do console.log (testbindbar); // função (consulte, após o bind, retorne uma nova função que atrasa a execução) testbindbar (); // 888Aqui devemos prestar atenção ao entendimento disso no protótipo.
A análise aprofundada acima das funções que se curreia em JavaScript Currying é todo o conteúdo que compartilho com você. Espero que você possa lhe dar uma referência e espero que você possa apoiar mais o wulin.com.