2016-02-10 3 views
1

я получил следующую реализацию батут:Понимание оптимизации батут для рекурсивных функций

function trampoline(f) { 
    while (f && f instanceof Function) { 

     f = f.apply(f.context, f.args); 

    } 
    return f; 
} 

И это работает так же, примером чего является факторный:

function factorial(n) { 
    function recur(n, acc) { 
     if (n == 0) { 
      return acc; 
     } else { 
      return recur.bind(null, n-1, n*acc); 
     } 
    } 
    return trampoline(recur.bind(null, n, 1)); 
} 

Проблема заключается в том, что я не понимаю, как f.context и f.args передаются в качестве аргументов, это свойства, которые явно не могут быть найдены при повторной функции внутри батута, когда я, например, попытаюсь получить доступ и console.log их. Затем он регистрирует значения undefined.

Каков механизм этой конкретной реализации, передающей аргументы функции?

+1

Можете ли вы уточнить, что преимущество использования батут, а не просто вызывая функцию «ванили»? –

+2

Javascript не оптимизирует хвостовую рекурсию по умолчанию, поэтому ее действительно легко превысить предел стека и производительность выхлопа. –

+0

Ваш код, кажется, работает нормально, можете ли вы прояснить проблему? –

ответ

2

Как вы можете видеть here, функциональные объекты не имеют свойства, называемые args и context, и именно поэтому они выглядят как undefined в журнале консоли. Внутри самой функции вы можете получить доступ к этим значениям в объектах arguments и this, но они не видны снаружи в связанных функциях (или несвязанных функциях).

Причина, по которой работает ваш код, заключается в том, что параметры apply добавляются, если функция связана с параметрами. Когда вы используете bind, вы можете привязать только контекст (это) или контекст и параметры. Если вы привязываете контекст и параметры, когда вы используете apply или call, то параметры, которые вы передаете, будут добавлены в конце списка параметров. В вашем конкретном случае, вы делаете ...

f = f.apply(undefined, undefined); 

... и результирующие параметры для F будет:

[...parametersWhenTheFunctionWasBound, undefined, undefined] 
+0

Спасибо. Я знаю, что нет таких свойств, следовательно, вопрос. Таким образом, он может быть нулевым или неопределенным, или простой вызов функции, поскольку это связывание просто задерживает выполнение как попытку частичного приложения. –

+0

Аргумент аргументов не игнорируется, а добавляется в список привязок. – Bergi

+0

Спасибо @Bergi, я собираюсь обновить ответ –

Смежные вопросы