Posso criar uma função recursiva em uma variável assim:
/* Count down to 0 recursively.
*/
var functionHolder = function (counter) {
output(counter);
if (counter > 0) {
functionHolder(counter-1);
}
}
Com isso, functionHolder(3);
daria saída 3
2
1
0
. Digamos que eu fiz o seguinte:
var copyFunction = functionHolder;
copyFunction(3);
produziria 3
2
1
0
como acima. Se eu mudar da functionHolder
seguinte forma:
functionHolder = function(whatever) {
output("Stop counting!");
Então functionHolder(3);
daria Stop counting!
, conforme o esperado.
copyFunction(3);
agora dá 3
Stop counting!
como se refere functionHolder
, não a função (para a qual ele mesmo aponta). Isso pode ser desejável em algumas circunstâncias, mas há uma maneira de escrever a função de modo que ela se chame a si mesma em vez da variável que a contém?
Ou seja, é possível mudar apenas a linha functionHolder(counter-1);
para que passando por todas essas etapas ainda dê 3
2
1
0
quando ligamos copyFunction(3);
? Eu tentei, this(counter-1);
mas deu um erro this is not a function
.
fonte
Respostas:
Usando expressões de função nomeada:
Você pode dar a uma expressão de função um nome que seja realmente privado e só seja visível de dentro da própria função:
Aqui
myself
é visível apenas dentro da própria função .Você pode usar este nome privado para chamar a função recursivamente.
Consulte
13. Function Definition
a especificação ECMAScript 5:Observe que o Internet Explorer até a versão 8 não se comporta corretamente, pois o nome está realmente visível no ambiente da variável envolvente e faz referência a uma duplicata da função real (consulte o comentário de patrick dw abaixo).
Usando argumentos.callee:
Como alternativa, você pode usar
arguments.callee
para se referir à função atual:A 5ª edição do ECMAScript proíbe o uso de arguments.callee () no modo estrito , no entanto:
fonte
myself
é realmente visível no ambiente de variável envolvente e faz referência a uma duplicata damyself
função real . Você deve ser capaz de definir a referência externa paranull
embora.return n * myself(n-1);
?Você pode acessar a função em si usando
arguments.callee
[MDN] :No entanto, isso será interrompido no modo estrito.
fonte
TypeError
, mas não encontrei nada que declare oficialmente quearguments.callee
(ou qualquer violação do modo estrito) está obsoleto fora do "modo estrito".Você pode usar o combinador Y: ( Wikipedia )
E você pode usá-lo assim:
fonte
Sei que essa é uma pergunta antiga, mas pensei em apresentar mais uma solução que poderia ser usada se você quiser evitar o uso de expressões de função nomeadas. (Não estou dizendo que você deve ou não evitá-los, apenas apresentando outra solução)
fonte
Aqui está um exemplo muito simples:
Observe que a
counter
contagem "para trás" em relação aoslug
valor é. Isso ocorre por causa da posição em que estamos registrando esses valores, pois a função se repete antes do registro - portanto, basicamente mantemos o aninhamento cada vez mais profundo na pilha de chamadas antes que o registro ocorra.Uma vez que a recursividade encontra o item final call-pilha, ele trampolins "fora" das chamadas de função, enquanto que, o primeiro incremento de
counter
ocorrer dentro da última chamada aninhada.Eu sei que isso não é uma "correção" no código do Questionador, mas dado o título, pensei em exemplificar genericamente a Recursão para uma melhor compreensão da recursão, de imediato.
fonte