Поддерживают ли связанные функции правильные вызовы в ES6? - PullRequest
0 голосов
/ 19 мая 2018

В спецификации языка ECMAScript 2015 определения Function.prototype.apply и Function.prototype.call оба включают «Perform PrepareForTailCall ()» в качестве одного из своих шагов, поэтому мы знаем, чтоэти функции поддерживают надлежащие вызовы хвоста (т. е. оптимизацию хвостового вызова).

Определение [[Call]] для связанных объектов функций , однако не включает PrepareForTailCall ().Означает ли это, что связанные функции не поддерживают надлежащие хвостовые вызовы и что связанная функция, вызывающая себя рекурсивно, может взорвать стек?

Ответы [ 2 ]

0 голосов
/ 19 мая 2018

Определение [[Call]] для связанных объектов функций опускает PrepareForTailCall().Означает ли это, что связанные функции не поддерживают надлежащие хвостовые вызовы, и что связанная функция, вызывающая себя рекурсивно, может взорвать стек?

Нет.PrepareForTailCall происходит в EvaluateDirectCall во время вычисления выражения вызова , где он проверяет, находится ли это выражение в хвостовой позиции.Когда хвостовой вызов подготовлен, текущий контекст выполнения сбрасывается до того, как функция будет вызываться , отправляя соответствующий внутренний метод [[Call]].Новый контекст текущего выполнения устанавливается в PrepareForOrdinaryCall из метода [[Call]] пользовательских функций .Метод связанных функций [[Call]] просто вводит дополнительный уровень косвенности до того, как это произойдет.

В Спецификации языка ECMAScript 2015 определения Function.prototype.apply и Function.prototype.call оба включают " Выполнить PrepareForTailCall()" в качестве одного из своих шагов, поэтому мы знаем, что эти функции поддерживают правильные вызовы хвоста.

Да, это необходимо, потому что [[Call]] метод встроенных функций устанавливает новый контекст выполнения (для «шагов, определенных реализацией»).Именно этот «встроенный контекст» будет отброшен PrepareForTailCall до вызова фактической функции.

Методы call и apply являются функциями, вызывающими функции, и при их вызове есть два вызовав стеке, который должен быть оптимизирован с помощью хвостового вызова.(Сравните это, например, с Array.prototype.map, который также вызывает другие функции, но здесь контекст выполнения map остается в стеке вызовов. В call и apply, Call() действительно находится в хвостеположение алгоритма).

0 голосов
/ 19 мая 2018

См. §12.3.4.1 ( Семантика времени выполнения: оценка ).Сначала мы делаем IsInTailPosition, затем EvaluateDirectCall - результат которого F.[[Call]].Другими словами, к тому времени, когда мы делаем реальный вызов, мы уже знаем, находимся ли мы в хвостовой позиции или нет.

Однако, как вы упоминаете, JS не оптимизирован для хвоста в любомбраузер , кроме Safari.

...