2012-01-10 15 views
5

Próbuję utworzyć rekurencyjną anonimową funkcję.Jak to działa javascript?

Oto funkcja:

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

wiem "to" jest obiektem okno. Czy istnieje sposób na wywołanie tej funkcji?

+1

** Najlepszym ** rzeczą do zrobienia jest to, że nie jest to funkcja anonimowa, lecz funkcja zdefiniowana za pomocą instrukcji deklaracji funkcji. – Pointy

Odpowiedz

12

Właściwość arguments.callee może być używana.

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

Inną metodą uzyskania tej samej funkcji jest użycie funkcji nazewnictwa. Poza zakresem, nazwa nie będzie dostępny:

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


pamiętać, że korzystanie z nieruchomości arguments.callee jest zabronione w trybie ścisłym:

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

rzuca:

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

+1

Dzięki! Spocznę mądrzej. –

+4

Zauważ, że 'arguments.callee' jest przestarzałe (i dość głośno, jeśli kiedykolwiek słyszałeś o nim na konferencji JavaScript) i nie będzie obsługiwane w przyszłości. Jest również dość powolny. Również nazwanie twoich funkcji, gdy są zdefiniowane za pomocą funkcji * expression * (w przeciwieństwie do deklaracji deklaracji) jest ryzykowne, ponieważ [przeglądarki czasami robią dziwne rzeczy.] (Http://kangax.github.com/nfe/) – Pointy

+0

Nie spodziewałem się nauczyć nowego słowa w tym wątku. "Vociferously" jest fantastyczny. –

1

Ah ... funkcjonalne formy rekursji .... [[flashback do comp sci class]]]

Można użyć funkcji pomocnika:

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

(która zwraca 720; jest silnia funkcja kanoniczna przykład rekursji)

ten może być z kolei anonimowe:

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

lub wyspecjalizowanych do funkcji jednego argumentu uniknąć apply i arguments:

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

(obie także zwracają 720)

Ta sztuczka korzystania z funkcji pomocnika umożliwia otrzymanie funkcji elf jako jego pierwszy argument, a przez to sam się nazywa.

Aby dostosować swój przykład:

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

który działa zgodnie z oczekiwaniami w Firebug (kłody 0,1,2,3,4,5 pocieszyć)

1

nadać nazwę funkcji anonimowej, tutaj nadaję mu nazwę "_", chociaż została ona nazwana, ale nadal jest anonimowa.

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