varargs passed length array argumentos argument javascript ecma262

passed - javascript params array



¿Por qué la propiedad argument.callee.caller está obsoleta en JavaScript? (5)

Es mejor usar funciones nombradas que argumentos.

function foo () { ... foo() ... }

es mejor que

function () { ... arguments.callee() ... }

La función nombrada tendrá acceso a su llamante a través de la propiedad del caller :

function foo () { alert(foo.caller); }

que es mejor que

function foo () { alert(arguments.callee.caller); }

La desaprobación se debe a los principios de diseño actuales de ECMAScript.

¿Por qué la propiedad arguments.callee.caller 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 ningún plan en el mapa para eliminar el soporte. Otros (Safari, Opera) han adoptado soporte para él, pero el soporte en navegadores más antiguos no es confiable.

¿Hay una buena razón para poner esta valiosa funcionalidad en el limbo?

(O alternativamente, ¿hay una mejor manera de agarrar una manija en la función de llamada?)


Las primeras versiones de JavaScript no permitían expresiones de funciones con nombre, y debido a eso no pudimos hacer una expresión de función recursiva:

// This snippet will work: function factorial(n) { return (!(n>1))? 1 : factorial(n-1)*n; } [1,2,3,4,5].map(factorial); // But this snippet will not: [1,2,3,4,5].map(function(n) { return (!(n>1))? 1 : /* what goes here? */ (n-1)*n; });

Para solucionar esto, se agregaron arguments.callee Se llamó para que pudiéramos hacer:

[1,2,3,4,5].map(function(n) { return (!(n>1))? 1 : arguments.callee(n-1)*n; });

Sin embargo, esta fue realmente una solución realmente mala, ya que esto (junto con otros argumentos, problemas de llamadas y personas que llaman) hace que la reclinación de la cola y la cola sean imposibles en el caso general (se puede lograr en casos seleccionados a través del rastreo, etc., pero incluso el mejor código es sub óptimo debido a las verificaciones que de otro modo no serían necesarias). El otro problema importante es que la llamada recursiva obtendrá un valor diferente a this , por ejemplo:

var global = this; var sillyFunction = function (recursed) { if (!recursed) return arguments.callee(true); if (this !== global) alert("This is: " + this); else alert("This is the global"); } sillyFunction();

De todos modos, EcmaScript 3 resolvió estos problemas permitiendo expresiones de funciones nombradas, por ejemplo:

[1,2,3,4,5].map(function factorial(n) { return (!(n>1))? 1 : factorial(n-1)*n; });

Esto tiene numerosos beneficios:

  • La función se puede llamar como cualquier otra desde dentro de su código.

  • No contamina el espacio de nombres.

  • El valor de this no cambia.

  • Es más eficaz (acceder al objeto de argumentos es caro).

Whoops,

Acabo de darme cuenta de que, además de todo lo demás, la pregunta era sobre los arguments.callee.caller , o más específicamente Function.caller

En cualquier momento, puede encontrar el interlocutor más profundo de cualquier función en la pila, y como dije anteriormente, mirar la pila de llamadas tiene un solo efecto importante: hace imposible un gran número de optimizaciones, 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ínea f . Básicamente, significa que cualquier sitio de llamada que haya sido trivialmente inlinable acumula un gran número de guardias, tome:

function f(a, b, c, d, e) { return a ? b * c : d * e; }

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 comprobaciones de todos los argumentos antes del código en línea o no puede integrar la función.

Ahora, en este caso particular, un intérprete inteligente debería poder reorganizar las verificaciones para que sean más óptimas y no verificar los valores que no se utilizarían. Sin embargo, en muchos casos eso no es posible y, por lo tanto, resulta imposible en línea.


Sólo una extensión. El valor de "esto" cambia durante la recursión. En el siguiente ejemplo (modificado), factorial obtiene el objeto {foo: true}.

[1,2,3,4,5].map(function factorial(n) { console.log(this); return (!(n>1))? 1 : factorial(n-1)*n; }, {foo:true} );

factorial llamado la primera vez obtiene el objeto, pero esto no es cierto para llamadas recursivas.


todavía hay un argumento para referirse a la función sin tener que codificar su nombre.


arguments.call ee .call er no está en desuso, aunque sí hace uso de la propiedad Function.caller . ( arguments.callee solo te dará una referencia a la función actual)

  • Function.call er , aunque no es estándar según ECMA3, se implementa en todos los principales navegadores actuales .
  • arguments.caller está en desuso a favor de Function.call er , y no está implementado en algunos de los principales navegadores actuales (por ejemplo, Firefox 3).

Por lo tanto, la situación no es ideal, pero si desea acceder a la función de llamada en Javascript en todos los navegadores principales, puede usar la propiedad Function.call er , ya sea que se accede directamente en una referencia de función nombrada, o desde una función anónima a través de los arguments.call ee propiedad arguments.call ee .