225 votes

Pourquoi les arguments.le destinataire de l'appel.appelant propriété obsolète en JavaScript?

Pourquoi l' arguments.callee.caller propriété obsolète en JavaScript?

Il a été ajouté, et puis obsolète en JavaScript, mais il a été complètement omis par ECMAScript. Certains navigateurs (Mozilla, IE) ont toujours soutenu, et n'ont pas de plans sur la carte à supprimer la prise en charge. D'autres (Safari, Opéra) ont adopté le soutien, mais le soutien sur les anciens navigateurs n'est pas fiable.

Est-il une bonne raison de mettre cette fonctionnalité précieuse dans les limbes?

(Ou sinon, est-il un meilleur moyen d'attraper une poignée sur l'appel de la fonction?)

264voto

olliej Points 16255

Les premières versions de JavaScript ne permet pas nommé les expressions de fonction, et ce parce que nous ne pouvions pas faire une fonction récursive expression:

 // 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;
 });

Pour contourner ce problème, arguments.callee a été ajouté, de sorte que nous pourrions faire:

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

Cependant, c'était effectivement une très mauvaise solution comme ceci (en conjonction avec d'autres arguments, appelant, et des problèmes de l'appelant) faire de l'in-lining et la queue de la récursivité impossible dans le cas général (vous pouvez la réaliser en cas de sélection par le biais de traçage, etc, mais même le meilleur code est sous-optimale en raison de contrôles qui autrement ne seraient pas nécessaires). L'autre problème majeur est que l'appel récursif obtiendrez un autre this de la valeur, par exemple:

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 toute façon, EcmaScript 3 résolu ces problèmes en permettant nommé les expressions de fonction, par exemple:

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

Cela a de nombreux avantages:

  • La fonction peut être appelée comme toutes les autres à partir de l'intérieur de votre code.

  • Il ne pollue pas l'espace de noms.

  • La valeur de this ne change pas.

  • Il est plus performant (l'accès à l' objet arguments est cher).

Oups,

Viens de réaliser que, en plus de tout le reste, la question était de savoir arguments.callee.caller, ou plus précisément Function.caller.

À n'importe quel point dans le temps, vous pouvez trouver le plus profond de l'appelant de la fonction sur la pile, et comme je l'ai dit ci-dessus, en regardant la pile d'appel a un effet majeur: Il fait un grand nombre d'optimisations impossible, ou beaucoup, beaucoup plus difficile.

Par exemple. si nous ne pouvons pas garantir qu'une fonction f ne seront pas appeler une fonction inconnue, alors il n'est pas possible de inline f. Fondamentalement, cela signifie que n'importe quel site d'appel qui peuvent avoir été trivialement inlinable accumule un grand nombre de gardes, de prendre:

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

Si le js interprète ne peut pas garantir que tous les arguments sont des nombres au point que l'appel est effectué, il doit insérer des contrôles pour tous les arguments avant de les inline code, ou s'il ne peut inline de la fonction.

Maintenant, dans ce cas particulier, un interprète intelligente devrait être en mesure de réorganiser les contrôles pour être plus optimale et de ne pas vérifier toutes les valeurs qui ne seraient pas utilisés. Cependant, dans de nombreux cas, c'est juste pas possible et, par conséquent, il devient impossible de la ligne.

90voto

James Wheare Points 2753

arguments.call est pas obsolète, bien qu'il ne faire usage de l' ee de la propriété. (.call va juste vous donner une référence à la fonction en cours)

  • er, bien que non-standard selon ECMA3, est mis en œuvre dans tous les principaux navigateurs actuels.
  • est déconseillée en faveur de l' Function.call, et n'est pas mis en œuvre dans certains principaux navigateurs actuels (par exemple, Firefox 3).

Donc, la situation n'est pas idéale, mais si vous souhaitez accéder à la fonction d'appel en Javascript dans tous les principaux navigateurs, vous pouvez utiliser l' er de la propriété, soit d'accéder directement à une fonction nommée de référence, ou dans une fonction anonyme via l' de la propriété.

29voto

Zach Points 9869

Il est préférable d'utiliser des fonctions nommées que les arguments.le destinataire de l'appel:

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

est mieux que

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

La fonction nommée aura accès à son appelant par l' appelant de la propriété:

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

ce qui est mieux que

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

La dépréciation est due à l'actualité ECMAScript principes de conception.

-1voto

matt b Points 73770

Je pense que vous voulez arguments.le destinataire de l'appel.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X