¿Por qué la arguments.callee.caller
propiedad quedó en desuso en JavaScript?
Fue agregado y luego desaprobado en JavaScript, pero fue omitido por completo por ECMAScript. Algunos navegadores (Mozilla, IE) siempre lo han admitido y no tienen planes en el mapa para eliminar el soporte. Otros (Safari, Opera) han adoptado soporte para él, pero el soporte en navegadores antiguos no es confiable.
¿Hay una buena razón para poner esta valiosa funcionalidad en el limbo?
(O, alternativamente, ¿hay una mejor manera de controlar la función de llamada?)
javascript
ecma262
pcorcoran
fuente
fuente
<b>
y<i>
regresamos (sí, esos fueron desaprobados en un punto).Respuestas:
Las primeras versiones de JavaScript no permitían expresiones de funciones con nombre, y por eso no pudimos hacer una expresión de función recursiva:
Para evitar esto,
arguments.callee
se agregó para que pudiéramos hacer:Sin embargo, esta fue realmente una solución realmente mala, ya que esto (junto con otros argumentos, llamadas y problemas de llamadas) hace que la reclinación de cola y la cola sean imposibles en el caso general (puede lograrlo en casos seleccionados a través del rastreo, etc., pero incluso el mejor código es subóptimo debido a controles que de otra forma no serían necesarios). El otro problema importante es que la llamada recursiva tendrá un
this
valor diferente , por ejemplo:De todos modos, EcmaScript 3 resolvió estos problemas al permitir expresiones de funciones con nombre, por ejemplo:
Esto tiene numerosos beneficios:
La función se puede llamar como cualquier otra dentro de su código.
No contamina el espacio de nombres.
El valor de
this
no cambia.Es más eficiente (acceder al objeto de argumentos es costoso).
Whoops
Me acabo de dar cuenta de que, además de todo lo demás, la pregunta se refería
arguments.callee.caller
, o más específicamenteFunction.caller
.En cualquier momento puede encontrar la llamada más profunda de cualquier función en la pila, y como dije anteriormente, mirar la pila de llamadas tiene un efecto importante: hace que una gran cantidad de optimizaciones sea imposible o mucho más difícil.
P.ej. Si no podemos garantizar que una función
f
no llame a una función desconocida, entonces no es posible en líneaf
. Básicamente significa que cualquier sitio de llamadas que puede haber sido trivialmente inlinable acumula una gran cantidad de guardias, tome:Si el intérprete js no puede garantizar que todos los argumentos proporcionados sean números en el momento en que se realiza la llamada, debe insertar verificaciones para todos los argumentos antes del código en línea, o no puede en línea la función.
Ahora, en este caso particular, un intérprete inteligente debería ser capaz de reorganizar las comprobaciones para que sean más óptimas y no verificar ningún valor que no se utilizaría. Sin embargo, en muchos casos eso simplemente no es posible y, por lo tanto, es imposible alinearse.
fuente
this
lo que creo que es irrelevante con respecto a si la persona que llama es buena o mala. Además, la persona que llama y la persona que llama solo están "en desuso" en modo estricto (ECMAscript ed 5, diciembre de 2009), pero supongo que eso no se sabía en 2008 cuando olliej publicó.this
ifthis
es el alcance global. En todos los demás casos, el valor dethis
va a cambiar después de la primera llamada recursiva, así que creo que las partes de su respuesta aludiendo a la preservación de lathis
realidad no son válidos.arguments.callee.caller
no está en desuso, aunque hace uso de la propiedad. ( solo le dará una referencia a la función actual)Function.caller
arguments.callee
Function.caller
, aunque no es estándar según ECMA3, se implementa en todos los principales navegadores actuales .arguments.caller
está en desuso a favor y no se implementa en algunos de los principales navegadores actuales (por ejemplo, Firefox 3).Function.caller
Por lo tanto, la situación es menos que ideal, pero si desea acceder a la función de llamada en Javascript en todos los principales navegadores, puede usar la propiedad, ya sea accediendo directamente en una referencia de función con nombre o desde una función anónima a través de la propiedad.
Function.caller
arguments.callee
fuente
arguments.callee
está prohibido en modo estricto. También me puso triste, pero es mejor no usarlo más.arguments.callee.caller
está en desuso en el modo estricto de ES5: "Otra característica que estaba en desuso fue argumentos.callee.caller, o más específicamente Function.caller". ( Fuente )Es mejor usar funciones nombradas que argumentos.callee:
es mejor que
La función nombrada tendrá acceso a su llamador a través de la propiedad llamante :
que es mejor que
La desaprobación se debe a los principios de diseño actuales de ECMAScript .
fuente
Solo una extensión. El valor de "esto" cambia durante la recursión. En el siguiente ejemplo (modificado), factorial obtiene el objeto {foo: true}.
El factorial llamado primera vez obtiene el objeto, pero esto no es cierto para las llamadas recursivas.
fuente
this
necesita mantenimiento, escribafactorial.call(this, n-1)
que realmente he encontrado al escribir código recursivo, que generalmente no existethis
, o sethis
refiere a algún nodo en un árbol y en realidad es bueno que cambie.