
Recomendações relacionadas: tutorial de javascript
apply(context,[arguments]) , call(context,param1,param2,...) .Currying é uma técnica que transforma uma função que aceita múltiplos parâmetros em uma função que aceita um único parâmetro (o primeiro parâmetro da função original), e retorna uma nova função que aceita os parâmetros restantes e retorna um resultado.
Por exemplo, aqui está uma função add() , que é uma função usada para processar a adição e soma dos parâmetros (param1, params2,...) que passamos para ela.
// Aqui está a primeira função `add(x, y)` com dois parâmetros `x`, `y` function add(x, y){
retornar x + y;
}
// Chame a função `add()` e forneça dois parâmetros `4` e `6`
adicionar(4,6);
//Simula a operação do computador, passa o primeiro parâmetro 4 no primeiro passo
função adicionar(4, y){
retorne 4 + y;
}
//Simula a operação do computador, passa o primeiro parâmetro 6 no segundo passo
função adicionar(4, 6){
retorne 4 + 6;
} Como seria se curríssemos a função add() ? Aqui está uma implementação simples:
// A função curried add() pode aceitar alguns parâmetros function add(x,y){
if (typeof y === 'indefinido') {
função de retorno (nova){
retornar x + novo;
}
}
// Retorno completo da aplicação x + y;
}
// Chamadas de teste console.log(typeof add(4));
console.log(add(4)(6));
// Você pode criar uma função de salvamento let saveAdd = add(4);
console.log(saveAdd(6)); // 10 Como pode ser visto na função curried add() simples acima, a função pode aceitar algumas funções e então retornar uma nova função para continuar processando as funções restantes.
Aqui criamos uma função de currying pública, para que não tenhamos que implementar o complexo processo de currying dentro dela toda vez que escrevemos uma função.
//Definir uma função createCurry function createCurry(fn){
var fatia = Array.prototype.slice,
storage_args = slice.call(argumentos,1);
função de retorno () {
deixe new_args = slice.call (argumentos),
args=armazenados_args.concat(novos_args);
retornar fn.apply(null,args);
}} Na função de currying pública acima:
arguments não é um array real, mas um objeto com um atributo length , então pegamos emprestado o método slice de Array.prototype para nos ajudar a converter arguments em um array real, para facilitar nossa melhor operação.createCurry pela primeira vez, a variável stored_args contém os parâmetros, exceto o primeiro parâmetro, porque o primeiro parâmetro é a função que precisamos curry.createCurry , a variável new_args obtém os parâmetros e os converte em um array.stored_args por meio do encerramento e mescla o valor da variável new_args em um novo array e o atribui à variável args .fn.apply(null,args) é chamado para executar a função curried.Agora vamos testar a função curried pública
// função ordinária add()
função adicionar(x, y){
retornar x + y;
}
// Curry para obter uma nova função var newAdd = createCurry(add,4);
console.log(newAdd(6));
//Outra maneira simples console.log(createCurry(add,4)(6));// 10 Claro, isso não se limita ao curry de dois parâmetros, mas também a vários parâmetros:
// Vários parâmetros A função comum function add (a,b,c,d){
retornar a + b + c + d;
}
// Curry a função para obter uma nova função, vários parâmetros podem ser divididos à vontade console.log(createCurry(add,4,5)(5,6));
// Curry em duas etapas let add_one = createCurry(add,5);
console.log(add_one(5,5,5));// 20
deixe add_two = createCurry(add_one,4,6);
console.log(add_two(6)); // 21Através do exemplo acima, podemos encontrar uma limitação, ou seja, sejam dois parâmetros ou vários parâmetros, só pode ser executado em duas etapas, como a seguinte fórmula:
se quisermos ser mais flexíveis:
)
Após os exercícios acima, descobrimos que a função com curry que criamos tem certas limitações. Esperamos que a função possa ser executada em várias etapas:
// Crie uma função com curry que possa ser executada em várias etapas Função. , execute-o quando o número de parâmetros for atendido:
// Fórmula da função: fn(x,y,z,w) ==> fn(x)(y)(z)(w);
deixe criarCurry = (fn,...params)=> {
deixe args = parsmos ||
let fnLen = fn.length; // Especifique o comprimento do parâmetro da função curried;
retornar (...res)=> {
// Obtém todos os parâmetros anteriores através da cadeia de escopo let allArgs = args.slice(0);
// Copie profundamente os parâmetros args compartilhados pelos encerramentos para evitar o impacto de operações subsequentes (tipo de referência)
allArgs.push(...res);
if(allArgs.length <fnLen){
// Quando o número de parâmetros for menor que o comprimento do parâmetro da função original, chame a função createCurry recursivamente return createCurry.call(this,fn,...allArgs);
}outro{
// Quando o número de parâmetros é atingido, aciona a execução da função return fn.apply(this,allArgs);
}
}
}
// Função comum function add(a,b,c,d){ com múltiplos parâmetros
retornar a + b + c + d;
}
//Teste a função currying let curryAdd = createCurry(add,1);
console.log(curryAdd(2)(3)(4)); // Implementamos funções de curry flexíveis há mais de 10 anos, mas aqui encontramos outro problema:
curryAdd(add,1,2,3,4)() ;add() original. Esta também é uma via, mas como estamos satisfazendo o número de parâmetros aqui, ainda lidamos com esta situação.Aqui só precisamos fazer um julgamento antes de retornar a função:
let createCurry = (fn,...params)=> {
deixe args = parsmos ||
let fnLen = fn.length; // Especifique o comprimento do parâmetro da função curried;
if(comprimento === _args.comprimento){
//Adicionar julgamento. Se o número de parâmetros pela primeira vez for suficiente, chame a função diretamente para obter o resultado return fn.apply(this,args);
}
retornar (...res)=> {
deixe allArgs = args.slice(0);
allArgs.push(...res);
if(allArgs.length <fnLen){
retornar createCurry.call(this,fn,...allArgs);
}outro{
return fn.apply(this,allArgs);
}
}} A função acima pode ser considerada uma função curry flexível, mas não é muito flexível aqui porque não podemos controlar quando ela é executada. Contanto que o número de parâmetros seja suficiente, ela será executada automaticamente. O que devemos fazer se quisermos atingir um timing que possa controlar a sua execução?
Vamos explicar diretamente a fórmula da função aqui:
// Quando os parâmetros forem satisfeitos, chame a função let createCurry = (fn,...params)=> {
deixe args = parsmos ||
let fnLen = fn.length; // Especifique o comprimento do parâmetro da função curried;
//É claro que o julgamento aqui precisa ser comentado, caso contrário o resultado será executado diretamente quando o número de parâmetros for suficiente pela primeira vez //if(length === _args.length){
// Adicione julgamento. Se o número de parâmetros pela primeira vez for suficiente, chame a função diretamente para obter o resultado //return fn.apply(this,args);
//}
retornar (...res)=> {
deixe allArgs = args.slice(0);
allArgs.push(...res);
// Aqui é avaliado se os parâmetros de entrada são maiores que 0. Se for maior que 0, é julgado se o número de parâmetros é suficiente.
// && não pode ser usado aqui Se && for usado, o resultado será executado quando o número de parâmetros for suficiente.
if(res.length > 0 || allArgs.length < fnLen){
retornar createCurry.call(this,fn,...allArgs);
}outro{
return fn.apply(this,allArgs);
}
}
}
// Função comum function add(a,b,c,d){ com múltiplos parâmetros
retornar a + b + c + d;
}
// Testa a função de curry controlável let curryAdd = createCurry(add,1);
console.log(curryAdd(2)(3)(4));
console.log(curryAdd(2)(3)(4)());
console.log(curryAdd(2)(3)()); // Retorna NaN quando os parâmetros não são suficientes. Recomendações relacionadas
: Tutorial de aprendizado de JavaScript.
preste atenção em php Outros artigos relacionados no site chinês!