Почему это arguments.callee.caller
свойство устарело в JavaScript?
Он был добавлен, а затем объявлен устаревшим в JavaScript, но в ECMAScript его вообще не использовали. Некоторые браузеры (Mozilla, IE) всегда поддерживали его и не планируют удалять поддержку на карте. Другие (Safari, Opera) приняли его поддержку, но поддержка в старых браузерах ненадежна.
Есть ли веская причина поставить этот ценный функционал в подвешенном состоянии?
(Или, альтернативно, есть ли лучший способ получить дескриптор вызывающей функции?)
javascript
ecma262
pcorcoran
источник
источник
<b>
и<i>
обратно (да, это были устаревшими в одной точке).Ответы:
Ранние версии JavaScript не допускали выражений именованных функций, и из-за этого мы не могли создать рекурсивное выражение функции:
Чтобы обойти это,
arguments.callee
был добавлен, чтобы мы могли сделать:Однако это было на самом деле очень плохое решение, так как (в сочетании с другими аргументами, проблемами вызываемого и вызывающего абонентов) делает невозможным встраивание и рекурсию хвоста в общем случае (вы можете добиться этого в некоторых случаях с помощью трассировки и т. Д., Но даже лучший код является субоптимальным из-за проверок, которые в противном случае не были бы необходимы). Другая важная проблема заключается в том, что рекурсивный вызов получит другое
this
значение, например:Так или иначе, EcmaScript 3 решил эти проблемы, позволив выражения именованных функций, например:
Это имеет множество преимуществ:
Функция может быть вызвана, как и любая другая из вашего кода.
Это не загрязняет пространство имен.
Значение
this
не меняется.Это более производительно (доступ к объекту arguments стоит дорого).
Упс,
Просто понял, что помимо всего прочего речь шла о
arguments.callee.caller
, а точнееFunction.caller
.В любой момент времени вы можете найти самого глубокого вызывающего абонента из любой функции в стеке, и, как я уже сказал выше, просмотр стека вызовов имеет один единственный важный эффект: он делает невозможным большое количество оптимизаций или намного более трудным.
Например. если мы не можем гарантировать, что функция
f
не будет вызывать неизвестную функцию, то встроить ее невозможноf
. По сути, это означает, что любой сайт вызова, который, возможно, был тривиально встроен, накапливает большое количество охранников, принимает:Если интерпретатор js не может гарантировать, что все предоставленные аргументы являются числами в момент выполнения вызова, ему необходимо либо вставить проверки для всех аргументов перед встроенным кодом, либо он не может встроить функцию.
Теперь в этом конкретном случае умный интерпретатор должен иметь возможность переставить проверки, чтобы они были более оптимальными, и не проверять какие-либо значения, которые не будут использоваться. Однако во многих случаях это просто невозможно, и, следовательно, становится невозможным встроить.
источник
this
поэтому я думаю, что это не имеет значения в отношении того, хорош ли вызываемый объект или нет. Кроме того, вызываемый и вызывающий абоненты "не рекомендуется" только в строгом режиме (ECMAscript ed 5, декабрь 2009 г.), но я думаю, что это не было известно в 2008 г., когда был опубликован olliej.this
if,this
являющееся глобальной областью действия. Во всех остальных случаях значениеthis
будет меняться после первого рекурсивного вызова, так что я думаю , что части вашего ответа намекая на сохранениеthis
не совсем корректные.arguments.callee.caller
не считается устаревшим, хотя он использует собственность. ( просто даст вам ссылку на текущую функцию)Function.caller
arguments.callee
Function.caller
хотя и нестандартный согласно ECMA3, он реализован во всех современных основных браузерах .arguments.caller
является устаревшим в пользу , а не реализована в некоторых текущих основных браузерах (например , Firefox 3).Function.caller
Таким образом, ситуация не идеальна, но если вы хотите получить доступ к вызывающей функции в Javascript во всех основных браузерах, вы можете использовать свойство, доступ к которому осуществляется непосредственно по ссылке на именованную функцию или из анонимной функции через свойство.
Function.caller
arguments.callee
источник
arguments.callee
в строгом режиме это запрещено. Это меня тоже огорчило, но лучше больше этим не пользоваться.arguments.callee.caller
не рекомендуется в строгом режиме ES5: «Еще одна особенность, которая устарела, была arguments.callee.caller или, более конкретно, Function.caller». ( Источник )Лучше использовать именованные функции, чем arguments.callee:
лучше, чем
Именованная функция будет иметь доступ к своему вызывающему через свойство вызывающего :
что лучше чем
Устаревание связано с текущими принципами проектирования ECMAScript .
источник
Просто продолжение. Значение «это» изменяется во время рекурсии. В следующем (измененном) примере factorial получает объект {foo: true}.
факториал, вызываемый впервые, получает объект, но это не так для рекурсивных вызовов.
источник
this
необходимо поддерживать, напишите,factorial.call(this, n-1)
что я действительно нашел в написании рекурсивного кода, которого обычно нетthis
, илиthis
ссылается на некоторый узел в дереве, и на самом деле это хорошо, что он изменяется.