Redéfinition de la fonction javascript

Est-il possible de redéfinir une fonction javascript à partir de son propre corps. Par exemple, je pourrais faire ce qui suit:

function never_called_again(args) { //do some stuff never_called_again = function (new_args) { //do some new stuff } } 

Est-ce que ce qui précède est valide et a-t-il la sémantique correcte? Je ne veux pas créer une nouvelle variable globale avec l'ancien nom de la fonction parce que j'essaye de faire ce genre de chose pas dans la portée globale, mais à partir de différentes étendues d'objets et je ne veux pas de conflits de noms lorsque je redéfinis la fonction Dans ces domaines locaux.

Oui, vous pouvez redéfinir une fonction de cette façon.

Exécuter ceci:

 function never_called_again(args) { console.log('Func 1', args); never_called_again = function (new_args, x) { console.log('Func 2', new_args, x); } } never_called_again('arg A', 'arg B'); never_called_again('arg A', 'arg B'); 

Rend le ceci:

 Func 1 arg A Func 2 arg A arg B 

Il est en effet possible de redéfinir une fonction de son corps. La technique est utilisée dans le soi-disant

Motif de définition de la fonction paresseuse

Cela ressemble à ceci:

 // Lazy Function Definition Pattern var foo = function() { var t = new Date(); foo = function() { return t; }; return foo(); } 

Ce que fait cette fonction est qu'il stocke la Date du premier appel, et renvoie cette date par la suite.

Si vous comparez cela avec le modèle du module , la différence est que l'initialisation ne se produit que lorsqu'il est appelé pour la première fois pas lorsqu'il est défini. Pour des amorçages coûteux, cela peut être très avantageux .

 // Conditional Module Pattern var foo = (function() { var t; return function() { if (t) { return t; } t = new Date(); return t; } })(); 

Votre exemple est essentiellement le même que:

 var never_called_again = function(args) { //do some stuff never_called_again = function (new_args) { //do some new stuff } } 

Comme vous le savez probablement, cela fonctionne:

 var a = 1; function myFunction() { //do some stuff a = 2; } myFunction(); alert(a) //==> 2 

Il est clair que le premier exemple fonctionne aussi.

Que vous vouliez vraiment faire cela ou non, c'est une question plus ouverte. Est-ce que cela rend le code plus difficile à comprendre?

Il est totalement possible de redéfinir un objet fonction dans ce que vous voulez lors du premier appel.

La raison pour laquelle cela est possible est que les évaluations d'affectation sont traitées de droite à gauche. Cela signifie que la portée de la fonction est saisie lorsque vous l'exécutez (dans ce cas, lorsque vous appelez la fonction). Ce que cela signifie vraiment, c'est qu'au moment de l'exécution, l'objet de fonction qui se réalise et la définition de fonction d'origine sont réellement 2 choses différentes, ce qui permet de redéfinir la fonction d'origine, bien … tout en rien.

L'un des meilleurs (et plus cool) moyens d'utiliser ceci est en créant une fonction qui est, en substance, sa propre usine. De cette façon, vous ne devez pas contenir beaucoup de définitions d'objets qui ne seront pas utilisées.

Exemple:

 d = function(type){ switch(type.toUpperCase()){ case 'A' : d = ( function(){ return { name : 'A', getName : function(){return this.name;} }; } )(); break; case 'B' : d = ( function(){ return { name : 'B', getName : function(){return this.name;} }; } )(); break; default: d = ( function(){ return { name : 'DEFAULT', getName : function(){return this.name;} }; } )(); break; } }; console.dir(d); d('A'); console.dir(d); console.log(d.getName()); 

Oui, c'est possible et il ne créera pas de fonction globale. J'ai vérifié ceci dans IE6, FF, Chrome, Opera. Considérez le code suivant:

  <head> <title>Never called again</title> <style type="text/css"> </style> <script type="text/javascript"> function hello() { function never_called_again(args) { alert("Hello world " + never_called_again); //do some stuff never_called_again = function (new_args) { //do some new stuff alert("hello " + never_called_again); } } never_called_again(); never_called_again(); } </script> </head> <body onload=""> <button onclick="hello(); never_called_again();">Call</button> </body> 

Cela imprimera "Hello World {code de fonction}" la première fois de la durée jamais annoncée et la deuxième fois, elle imprimera "bonjour {code de fonction changé}" la deuxième fois. Mais quand on appelle l'onclick du bouton, il lancera une erreur en disant que la fonction n'est pas définie, indiquant clairement que la fonction a été redéfinie (et non créée à l'échelle mondiale).

À strictement parler, non, il n'est pas possible de redéfinir une fonction JavaScript. Bien que ce soit une question de sémantique.

Une fonction peut remplacer sa référence dans une certaine portée avec une autre fonction, qui sert de manœuvre de main où une autre fonction apparaît à la place du premier. par exemple

 greet_once = function() { console.log('Hello.'); greet_one = function() { console.log('Can I help you?') }; }; 

De même, une fonction peut utiliser l'état d'une portée fermée pour se comporter différemment, la deuxième fois appelée (évidemment pas "redéfinition").

L'exemple suivant illustre pourquoi le modèle ci-dessus n'est pas une redéfinition, car cela dépend de la portée parentale qui peut ne pas être partagée avec la portée d'appel.

 greet_always = function() { greet_once = function() { console.log('Hello.') greet_one = function() { console.log('Can I help you?') } }; return one_timer }() greet_always() greet_always() 

La fonction appelée greet_always (qui imprime toujours 'Bonjour') est la même, assignée initialement à greet_once .

Le plus proche, je crois que vous pouvez redéfinir une fonction, est de réaffecter ses méthodes d'application et d'appel, ce qui produit un scénario où myFunction.call() est différent de myFunction() , ce qui est étrange mais utile.