2012-01-10 15 views
5

Sto provando a creare una funzione anonima ricorsiva.Come rendere questo javascript funzionante?

Qui è la funzione:

(function (i) { 
    console.log(i); 
    if (i < 5) this(i + 1) 
})(0) 

So che "questo" è l'oggetto finestra. C'è un modo per chiamare la funzione?

+1

La cosa migliore da fare è non avere una funzione anonima, ma una funzione definita con una dichiarazione di funzione. – Pointy

risposta

12

È possibile utilizzare la proprietà arguments.callee.

(function(i){console.log(i);if(i<5)arguments.callee(i+1)})(0) 

Un altro metodo per ottenere la stessa funzionalità è la funzione di denominazione. Al di fuori del campo di applicazione, il nome non sarà disponibile:

(function tmp(i){console.log(i);if(i<5)tmp(i+1)})(0); //OK, runs well 
alert(typeof tmp); // Undefined 


Nota che l'uso della proprietà arguments.callee è vietato in modalità rigorosa:

"use strict"; 
(function(){arguments.callee})(); 

getta:

TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them

+1

Grazie! Dormirò più intelligente. –

+4

Nota che 'arguments.callee' è deprecato (e abbastanza rumorosamente, se ne hai mai sentito parlare in una conferenza JavaScript), e non sarà supportato in futuro. È anche piuttosto lento. Inoltre, nominare le proprie funzioni quando sono definite con una funzione * espressione * (al contrario di una dichiarazione) è rischioso perché [i browser a volte fanno cose strane.] (Http://kangax.github.com/nfe/) – Pointy

+0

Non mi aspettavo di imparare una nuova parola su questo thread. "Vociforme" è fantastico. –

1

Ah ... le forme funzionali di ricorsione .... [[[flashback alla classe comp sci]]]

Si potrebbe utilizzare una funzione di supporto:

function X(f) { return f.apply(this, arguments); } 
X(function(me, n) { return n<=1 ? n : n*me(me,n-1); }, 6); 

(che restituisce 720; questa è la funzione fattoriale, l'esempio canonico di ricorsione)

Ciò può a sua volta essere anonimi:

(function (f) { return f.apply(this, arguments); })(
    function(me, n) { return n<=1 ? n : n*me(me,n-1); }, 
    6); 

o specializzato per funzioni di un argomento, evitare apply e arguments:

(function (f,x) { return f(f,x); })(
    function(me, n) { return n<=1 ? n : n*me(me,n-1); }, 
    6); 

(entrambi restituiscono anche 720)

Questo trucco dell'utilizzo di una funzione di supporto consente alla funzione di ricevere il suo elfo come primo argomento, e quindi si chiama.

Per adattare il tuo esempio:

(function (f,x) { return f(f,x); })(
    function(me, i) { console.log(i); if (i<5) me(me,i+1); }, 
    0) 

che funziona come previsto in Firebug (ceppi 0,1,2,3,4,5 per console)

1

si dà un nome alla funzione anonima, qui gli do un nome "_", anche se è chiamato, ma è ancora anonimo.

(function _(i) { 
    console.log(i); 
    if (i < 5){ _(i + 1); } 
})(0); 
Problemi correlati