Cette page a été traduite à partir de l'anglais par la communauté.Vous pouvez contribuer en rejoignant la communauté francophone sur MDN Web Docs.
callee
Obsolète: Cette fonctionnalité n'est plus recommandée. Même si certains navigateurs la prennent encore en charge, elle a peut-être déjà été supprimée des standards du web, est en passe d'être supprimée ou n'est conservée qu'à des fins de compatibilité. Évitez de l'utiliser et mettez à jour le code existant si possible ; consultez letableau de compatibilité au bas de cette page pour vous aider à prendre votre décision. Sachez que cette fonctionnalité peut cesser de fonctionner à tout moment.
La propriétéarguments.callee contient la fonction en cours d'exécution.
Dans cet article
Description
callee est une propriété de l'objetarguments. Elle peut être utilisée afin de faire référence à la fonction en cours d'exécution à l'intérieur de cette fonction. Cette propriété peut etre utile lorsqu'on ne connait pas le nom de la fonction (fonction anonyme par exemple).
Attention :Enmode strict, ECMAScript 5 interdit la fonctionarguments.callee(). Éviter de l'utiliser en utilisant un nom de fonction dans les expressions ou en utilisant une déclaration de fonction où la fonction s'appelle elle-même.
Pourquoiarguments.callee a-t-il été retiré du mode strict ES5 ?
(adapté d'une réponseStack Overflow par olliej)
Aux débuts de JavaScript, il n'était pas possible d'utiliser des expressions de fonction avec des noms. Il était donc impossible de faire une expression de fonction récursive.
Cette syntaxe produisait le résultat escompté :
function factorielle(n) { return !(n > 1) ? 1 : factorielle(n - 1) * n;}[1, 2, 3, 4, 5].map(factorielle);mais :
[1, 2, 3, 4, 5].map(function (n) { return !(n > 1) ? 1 : /* que met-on ici ? */ (n - 1) * n;});ne fonctionnait pas. Pour que cela puisse fonctionner, on ajoutaarguments.callee :
[1, 2, 3, 4, 5].map(function (n) { return !(n > 1) ? 1 : arguments.callee(n - 1) * n;});Cependant, ce fut une mauvaise solution (aveccaller également) car elle rendit impossible l'extension inline et larécursion terminale de façon générale (il est possible d'y arriver de certaines façons mais cela entraînerait nécessairement un code moins efficace). Le second problème que cela entraîne est que l'appel récursif aura une autre valeurthis :
var global = this;var fonctionTruc = function (recursed) { if (!recursed) { return arguments.callee(true); } if (this !== global) { console.log("this est : " + this); } else { console.log("this est la variable globale"); }};fonctionTruc();ECMAScript 3 a introduit les expressions de fonctions nommées pour résoudre le problème. On peut désormais utiliser :
[1, 2, 3, 4, 5].map(function factorielle(n) { return !(n > 1) ? 1 : factorielle(n - 1) * n;});Cette méthode possède plusieurs avantages :
- La fonction peut être appelée comme n'importe quelle autre fonction nommée dans le code
- Cela ne crée pas une variable dans la portée extérieure (sauf pour IE 8 et les versions antérieures)
- Cela entraîne de meilleures performances que d'accéder aux propriétés de l'objet
arguments
Une autre fonctionnalité qui a été déprécié est :arguments.callee.caller, ou plus précisémentFunction.caller. Pourquoi cela ? Parce que ça permet d'avoir accès à tout moment à la fonction appelante la plus loin dans la pile d'appels. Or, comme évoqué ci-avant, cela a un effet de bord considérable : ça rend beaucoup plus complexes voire impossibles certaines optimisations. Ainsi, on ne peut pas garantir qu'une fonctionf n'appellera pas une autre fonction inconnue, ce qui signifie qu'on ne peut pas utiliser l'extension inline. En résumé, cela signifie que n'importe quel site d'appel de fonction (call site) qui aurait pu être développé inline très simplement devra subir de nombreux tests :
function f(a, b, c, d, e) { return a ? b * c : d * e;}Si l'interpréteur JavaScript ne peut pas garantir que l'ensemble des arguments fournis ici sont des nombres à l'instant de l'appel de la fonction, il devra insérer des vérifications pour chaque argument avant le code inline, sinon il ne pourra pas développer la fonction inline. On notera que, dans ce cas, un interpréteur intelligent devrait pouvoir réarranger les vérifications à faire afin qu'elles soient optimales et de se débarrasser des valeurs inutiles. Malgré tout, une telle optimisation ne sera pas possible dans d'autres cas, ce qui signifie que le développement inline n'est pas possible.
Exemples
>Utiliserarguments.callee pour une fonction anonyme récursive
Une fonction récursive, par définition, s'appelle elle-même. Elle fait donc généralement référence à elle-même grâce à son nom. Cependant, une fonction anonyme (créée grâce ) uneexpression de fonction ou au constructeurFunction) n'a pas de nom et la seule façon d'y faire référence est donc d'utiliserarguments.callee.
L'exemple qui suit illustre une fonction qui définit et renvoie une fonction factorielle. Cet exemple n'a qu'un but démonstratif et ne correspond certainement pas à ce qui serait utilisé en pratique (les expressions de fonctions pouvant êtrenommées).
function créer() { return function (n) { if (n <= 1) return 1; return n * arguments.callee(n - 1); };}var résultat = create()(5); // renvoie 120 (5 * 4 * 3 * 2 * 1)Une utilisation d'arguments.callee qui ne possède pas de solution de remplacement
Malgré tout, dans un cas comme le suivant, il n'existe pas d'équivalent pourarguments.callee, c'est pourquoi sa déprécation pourrait être un bug (voirbug Firefox 725398):
function créerPersonne(sIdentité) { var oPersonne = new Function("alert(arguments.callee.identité);"); oPersonne.identité = sIdentité; return oPersonne;}var jean = créerPersonne("Jean Biche");jean();Spécifications
| Specification |
|---|
| ECMAScript® 2026 Language Specification> # sec-arguments-exotic-objects> |