9
votes

JavaScript: ré-attribuer une fonction avec une autre fonction

Disons que j'ai ces deux fonctions: xxx

maintenant, si j'appelle foo () , je vois inchangé , comme attendu. Toutefois, si j'appelle fnchanger d'abord, je vois toujours inchangé : xxx

maintenant, je suppose que c'est parce que Code> FOO n'est pas transmis à FnCHanger par référence, mais je me trompe peut-être.

pourquoi fnChanger ne change pas > FOO pour imprimer modifié! ?
En outre, comment puis-je obtenir fnchanger pour changer foo sans trop de syntaxe désordonnée?

ps: j'utilise node.js pour tester tout cela Strip, c'est là que le sys.print vient de.


0 commentaires

4 Réponses :


6
votes

L'affectation à l'argument fn permet simplement à cet identifiant de pointer sur la fonction anonyme, foo dans la portée extérieure n'est pas affecté.

Quand vous passez un Objet comme un argument, on peut dire «les références sont transmises par la valeur». L'affectation remplace simplement l'emplacement où l'identifiant fn fait référence à.

C'est comme ça que c'est comment stratégie d'évaluation fonctionne dans JavaScript.

juste avant l'affectation dans les fonctions FnCHanger , les deux identifiants, les deux identifiants, le Global FOO et l'argument fn , pointez sur le même objet de fonction: xxx

après l'affectation, fn signalera simplement la nouvelle fonction: xxx

Comment pouvez-vous le changer?

Eh bien, en supposant que foo < / code> est une fonction de la portée globale, vous pouvez faire quelque chose comme ceci: xxx

ce qui précède fonctionnera car dans la fonction fnCHanger , Nous avons besoin d'un objet objet de base et d'un nom de propriété , les fonctions déclarées dans le contexte d'exécution global sont liées comme propriétés de l'objet global , nous pouvons donc nous pouvons ré-attribuer sa valeur de cette manière.

t il ligne fnCHanger (ceci, 'foo'); doit être exécuté également dans la portée globale, il passera la valeur de cette (qui fait référence à l'objet global dans cette portée. ) et un nom de propriété, vous permettant de créer une affectation au Identificateur .

Si ce code était à l'intérieur d'une fonction, il n'y a aucun moyen que nous puissions obtenir un < em> l'objet de base , car dans ce "contexte d'exécution de code de fonction", les déclarations de fonctions (déclarations variables et paramètres formels de fonction également) sont liées comme propriétés d'un objet non accessible , appelé le Objet variable (une chaîne de ces objets variables, forme la chaîne d'étendue), et si c'était le cas, la seule solution de contournement serait d'utiliser eval .

Plus d'infos: < / p>


2 commentaires

Oui, je commençais à soupçonner que c'est ce qui se passe. Merci pour la clarification et le lien - je n'ai jamais su exactement quoi d'appeler ou comment cela a fonctionné. Comment puis-je me contourner ça?


Ok, j'aime cette approche. Pas aussi désordonné que je pensais faire: passer un objet contenant la fonction à changer.



4
votes

Comme @CMS a indiqué que vous ne pouvez pas l'affecter dans la fonction en raison de la portée. Cependant, vous pouvez le réaffecter comme ceci comme suit: xxx

exemple


1 commentaires

Oui, pensa à cela. Je suis hésitant à le faire par retour dans le code réel, cependant. D'une part, c'est plus propre, mais de l'autre, cela ne correspond pas à ce que la fonction fait réellement.



0
votes

Il y a un moyen élégant autour de celui-ci xxx

explication courte:

  1. Passez une référence de niveau supérieur foo_holder à FnChange comme un hachage (ou un tableau).
  2. Réassignez votre élément à l'intérieur du hachage FOO_HOLDER ["FN"] à une nouvelle valeur. Cela changera lorsque la référence interne pointe au lieu de créer une nouvelle référence.
  3. Alors vous êtes prêt à vous amuser avec votre fonction mise à jour.

0 commentaires

0
votes

en JavaScript, les fonctions sont des objets de première classe pouvant être traités comme une autre variable forte>. Mais pour la fonction de renvoyer son résultat, il doit être invoqué pour la première fois.

Lorsque vous appelez le FnCHanger (FOO), la variable FN est réellement remplacée avec FOO (). P>

mais vous êtes ne pas obtenir le résultat parce que cette fonction n'a jamais été invoquée. Essayez de le renvoyer et d'appeler comme indiqué ci-dessous et que vous allez la réponse requise. P>

p>

function fnChanger(fn) {
  fn = function() {
    console.log('Changed!');
  }
  return fn;
}

function foo() {
  console.log('Unchanged');
}

fnChanger(foo)();
foo();


0 commentaires