Puedo crear una función recursiva en una variable así:
/* Count down to 0 recursively.
*/
var functionHolder = function (counter) {
output(counter);
if (counter > 0) {
functionHolder(counter-1);
}
}
Con esto, functionHolder(3);
saldría 3
2
1
0
. Digamos que hice lo siguiente:
var copyFunction = functionHolder;
copyFunction(3);
saldría 3
2
1
0
como arriba. Si luego cambié de la functionHolder
siguiente manera:
functionHolder = function(whatever) {
output("Stop counting!");
Entonces functionHolder(3);
daría Stop counting!
, como se esperaba.
copyFunction(3);
ahora da lo 3
Stop counting!
que se refiere functionHolder
, no la función (a la que él mismo apunta). Esto podría ser deseable en algunas circunstancias, pero ¿hay alguna forma de escribir la función para que se llame a sí misma en lugar de a la variable que la contiene?
Es decir, ¿es posible cambiar solo la línea functionHolder(counter-1);
para que seguir todos estos pasos aún dé 3
2
1
0
cuando llamemos copyFunction(3);
? Lo intenté this(counter-1);
pero eso me da el error this is not a function
.
fuente
Respuestas:
Uso de expresiones de función con nombre:
Puede darle a una expresión de función un nombre que sea realmente privado y solo sea visible desde el interior de la función ifself:
Aquí
myself
es visible solo dentro de la función en sí.Puede utilizar este nombre privado para llamar a la función de forma recursiva.
Consulte
13. Function Definition
la especificación ECMAScript 5:Tenga en cuenta que Internet Explorer hasta la versión 8 no se comporta correctamente ya que el nombre es realmente visible en el entorno de la variable adjunta y hace referencia a un duplicado de la función real (consulte el comentario de patrick dw a continuación).
Usando argumentos.callee:
Alternativamente, puede usar
arguments.callee
para referirse a la función actual:La quinta edición de ECMAScript prohíbe el uso de argumentos.callee () en modo estricto , sin embargo:
fuente
myself
es realmente visible en el entorno de la variable adjunta, y hace referencia a un duplicado de lamyself
función real . Sinnull
embargo, debería poder establecer la referencia externa a .return n * myself(n-1);
?Puede acceder a la función en sí usando
arguments.callee
[MDN] :Sin embargo, esto se romperá en modo estricto.
fuente
TypeError
, pero no he encontrado nada que indique oficialmente quearguments.callee
(o cualquier violación del modo estricto) está desaprobado fuera del "modo estricto".Puede utilizar el combinador Y: ( Wikipedia )
Y puedes usarlo así:
fuente
Sé que esta es una pregunta antigua, pero pensé en presentar una solución más que podría usarse si desea evitar el uso de expresiones de función con nombre. (No digo que debas o no debes evitarlos, solo presenta otra solución)
fuente
Aquí hay un ejemplo muy simple:
Observe que la
counter
cuenta "al revés" con respecto a cuálslug
es el valor. Esto se debe a la posición en la que estamos registrando estos valores, ya que la función se repite antes del registro; por lo tanto, esencialmente seguimos anidando cada vez más profundamente en la pila de llamadas antes de que se realice el registro.Una vez que la recursividad se encuentra con el último punto pila de llamadas, que trampolines "fuera" de las llamadas de función, mientras que, el primer incremento de
counter
produce en el interior de la última llamada anidada.Sé que esto no es una "solución" en el código del Interlocutor, pero dado el título, pensé que ejemplificaría genéricamente la recursividad para una mejor comprensión de la recursividad, directamente.
fuente