Dlaczego arguments.callee.caller
właściwość jest przestarzała w JavaScript?
Został dodany, a następnie przestarzały w JavaScript, ale został całkowicie pominięty przez ECMAScript. Niektóre przeglądarki (Mozilla, IE) zawsze ją obsługiwały i nie mają żadnych planów na mapie, aby usunąć wsparcie. Inne (Safari, Opera) przyjęły wsparcie dla niego, ale obsługa starszych przeglądarek jest zawodna.
Czy istnieje dobry powód, by tę cenną funkcjonalność wprowadzić w stan zawieszenia?
(Lub na przemian, czy jest lepszy sposób na uchwycenie funkcji wywołania?)
javascript
ecma262
pcorcoran
źródło
źródło
<b>
i<i>
wróciliśmy (tak, były one przestarzałe w pewnym momencie).Odpowiedzi:
Wczesne wersje JavaScript nie pozwalały na nazwane wyrażenia funkcyjne, dlatego nie mogliśmy utworzyć rekurencyjnego wyrażenia funkcyjnego:
Aby obejść ten problem,
arguments.callee
dodano, abyśmy mogli:Było to jednak naprawdę złe rozwiązanie, ponieważ (w połączeniu z innymi argumentami, sprawami wywoływanymi i wywołującymi) uniemożliwia wstawianie i rekurencję ogona w ogólnym przypadku (można to osiągnąć w wybranych przypadkach przez śledzenie itp., Ale nawet najlepszy kod jest poniżej optymalnego ze względu na kontrole, które w innym przypadku nie byłyby konieczne). Innym ważnym problemem jest to, że wywołanie rekurencyjne otrzyma inną
this
wartość, na przykład:W każdym razie EcmaScript 3 rozwiązał te problemy, umożliwiając nazwane wyrażenia funkcji, np .:
Ma to wiele zalet:
Funkcja może być wywoływana jak każda inna z twojego kodu.
Nie zanieczyszcza przestrzeni nazw.
Wartość
this
nie zmienia się.Jest bardziej wydajny (dostęp do obiektu argumentów jest kosztowny).
Ups,
Właśnie zdałem sobie sprawę, że oprócz wszystkiego innego pytanie dotyczyło
arguments.callee.caller
, a dokładniejFunction.caller
.W dowolnym momencie na stosie można znaleźć najgłębszą funkcję wywołującą dowolną funkcję, a jak powiedziałem powyżej, przeglądanie stosu wywołań ma jeden istotny efekt: uniemożliwia lub znacznie utrudnia dużą liczbę optymalizacji.
Na przykład. jeśli nie możemy zagwarantować, że funkcja
f
nie wywoła nieznanej funkcji, nie można wstawićf
. Zasadniczo oznacza to, że każda strona wywoławcza, która mogła być trywialnie nieuchronna, gromadzi dużą liczbę strażników, weź:Jeśli interpreter js nie może zagwarantować, że wszystkie podane argumenty są liczbami w momencie wywołania, musi albo wstawić sprawdzanie wszystkich argumentów przed wstawionym kodem, albo nie może wstawić funkcji.
Teraz w tym konkretnym przypadku inteligentny tłumacz powinien być w stanie zmienić kolejność sprawdzania, aby był bardziej optymalny i nie sprawdzał żadnych wartości, które nie byłyby używane. Jednak w wielu przypadkach jest to po prostu niemożliwe i dlatego niemożliwe staje się wprowadzenie.
źródło
this
więc myślę, że nie ma znaczenia, czy odbiorca jest dobry, czy zły. Ponadto odbiorca i osoba dzwoniąca są „przestarzałe” tylko w trybie ścisłym (ECMAscript ed 5, grudzień 2009), ale myślę, że nie było to znane w 2008 roku, kiedy opublikował to olliej.this
ifthis
. We wszystkich pozostałych przypadkach, wartośćthis
będzie zmienić po pierwszym wywołaniu rekurencyjnym, więc myślę, że poszczególne części odpowiedź nawiązując do zachowaniathis
nie są naprawdę ważne.arguments.callee.caller
nie jest przestarzałe, chociaż korzysta z właściwości. ( poda tylko odniesienie do bieżącej funkcji)Function.caller
arguments.callee
Function.caller
, chociaż niestandardowy zgodnie z ECMA3, jest implementowany we wszystkich głównych przeglądarkach .arguments.caller
jest przestarzałe na rzecz i nie jest zaimplementowane w niektórych głównych przeglądarkach (np. Firefox 3).Function.caller
Sytuacja jest więc mniej niż idealna, ale jeśli chcesz uzyskać dostęp do funkcji wywołującej w Javascripcie we wszystkich głównych przeglądarkach, możesz użyć tej właściwości, albo bezpośrednio w nazwanym odwołaniu do funkcji, albo z funkcji anonimowej za pośrednictwem tej właściwości.
Function.caller
arguments.callee
źródło
arguments.callee
jest zabroniony w trybie ścisłym. Też mnie zasmuciło, ale lepiej go nie używać.arguments.callee.caller
przestarzała w trybie ścisłym ES5: „Kolejną przestarzałą funkcją była arguments.callee.caller, a dokładniej Function.caller”. ( Źródło )Lepiej jest używać nazwanych funkcji niż arguments.callee:
jest lepszy niż
Nazwana funkcja będzie miała dostęp do swojego obiektu wywołującego za pośrednictwem właściwości obiektu wywołującego :
co jest lepsze niż
Wycofanie wynika z bieżącego ECMAScript zasad projektowania .
źródło
Tylko rozszerzenie. Wartość „this” zmienia się podczas rekurencji. W poniższym (zmodyfikowanym) przykładzie silnia pobiera obiekt {foo: true}.
silnia wywoływana za pierwszym razem pobiera obiekt, ale nie dotyczy to wywołań rekurencyjnych.
źródło
this
trzeba to utrzymać, napiszfactorial.call(this, n-1)
, że znalazłem już podczas pisania kodu rekurencyjnego, że zwykle nie mathis
, lubthis
odnosi się do jakiegoś węzła w drzewie i tak naprawdę dobrze, że się zmienia.