Как заставить этот JavaScript работать? - PullRequest
5 голосов
/ 11 января 2012

Я пытаюсь создать рекурсивную анонимную функцию.

Вот эта функция:

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

Я знаю, что "это" - объект окна.Есть ли способ вызвать функцию?

Ответы [ 3 ]

12 голосов
/ 11 января 2012

Можно использовать свойство arguments.callee.

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

Еще один метод для достижения той же функциональности - использование функции именования.Вне области, имя не будет доступно:

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

Обратите внимание, что использование свойства arguments.callee запрещено в строгом режиме:

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

throws:

TypeError: 'caller', 'callee'и свойства 'arguments' не могут быть доступны для функций строгого режима или объектов аргументов для их вызова

1 голос
/ 27 января 2013

Вы даете имя анонимной функции, здесь я даю ей имя "_", хотя она и названа, но все еще анонимна.

(function _( i ) {
  console.log(i);
  if (i < 5){ _(i + 1); }
})(0);
1 голос
/ 11 января 2012

Ах ... функциональные формы рекурсии .... [[[flashback to comp sci class]]]

Вы можете использовать вспомогательную функцию:

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

(возвращает 720; это факториальная функция, канонический пример рекурсии)

Это, в свою очередь, может быть анонимизировано:

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

или специализировано для функций одного аргумента, чтобы избежать apply и arguments:

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

(оба из которых также возвращают 720)

Этот прием использования вспомогательной функции позволяет вашей функции получать себя в качестве первого аргумента и, таким образом, вызыватьсам по себе.

Чтобы адаптировать ваш пример:

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

, который работает, как и ожидалось, в Firebug (протоколирует 0,1,2,3,4,5 в консоль)

...