Comprendre le comportement des variables Lorsqu'ils transposent la récursivitéComprendre le comportement des variables lorsque La mise en œuvre Recursion Problème que vous voulez mettre en oeuvre la récursivité en JavaScript, et vous voulez aussi de comprendre comment les variables se comportent dans ces circonstances. Théorie En JavaScript, vous n'avez pas besoin de déclarer le type de variable, ou même déclarer la variable. Par exemple, le code suivant fonctionne parfaitement: if (compteur == 1) ( tampon = "Est à 1";) document.getElementById ( "result"). InnerHTML = tampon; La variable tampon n'a pas été déclaré devant le si le bloc dans le code précédent. La dernière ligne du code utilise la variable buffer assigner à la propriété innerHTML. Ce genre de déclaration est problématique, car de mémoire tampon peut être indéfini. JavaScript ne mentionne pas cela comme une erreur, et innerHTML sera affecté la valeur indéfinie. Cet exemple montre que les variables en JavaScript peut se comporter de façons dont une avec un programmeur Java ou C # background mai ne pas être habitués. L'objectif de cette recette est à comprendre comment se comporte une variable dans différents contextes. Un contexte exemple est la mise en oeuvre de la récursivité en JavaScript. Solution Deux fonctions qui mettent en oeuvre la récursivité par exemple en JavaScript suivre. Source: / website / ROOT / ajaxrecipes / javascript / fonction variablebehavior.html RecursionGlobal (compteur) (info ( "RecursionGlobal (localCounter)", typeof (localCounter)); localCounter = counter; info ( "RecursionGlobal (localCounter)", localCounter); si (localCounter <3) (RecursionGlobal (localCounter + 1);)) function RecursionLocal (compteur) (info ( "RecursionLocal (localCounter)", typeof (localCounter)); var = localCounter comptoir info ( "RecursionLocal (localCounter)", localCounter); if (localCounter <3) (RecursionLocal (localCounter + 1);)) L'exemple montre deux méthodes: RecursionGlobal et RecursionLocal. Entre les deux méthodes il ya une différence unique, comme indiqué dans le code en gras: le mot-clé var JavaScript. Le Var mot clé unique est la variation sur la façon dont la variable localCounter est stocké. Le comportement des deux méthodes est identique lorsqu'il est exécuté et génère le même résultat. Vous mai pense à première vue que le mot-clé var ne sert aucun but. Mais le mot-clé var répond à un objectif, qui est illustrée par l'exécution du programme suivant: Info: recursion_global *** DEBUT *** Info: RecursionGlobal () localCounter undefined Info: RecursionGlobal () localCounter 1 Infos: RecursionGlobal () localCounter nombre Info: RecursionGlobal () localCounter 2 Info: RecursionGlobal () localCounter nombre Info: RecursionGlobal (localCounter ) 3 Infos: recursion_local *** DEBUT *** Info: RecursionLocal () localCounter undefined Info: RecursionLocal () localCounter 1 Infos: RecursionLocal () localCounter undefined Info: RecursionLocal () localCounter 2 Info: RecursionLocal () localCounter undefined Info: RecursionLocal localCounter () 3
Notez que lorsque la fonction RecursionGlobal s'exécute, le type de la localCounter pour le premier appel est indéfini, et par la suite, il est numéro. En revanche, lorsque la fonction RecurisonLocal est appelée, le type de localCounter n'est pas définie pour chaque appel. Cela signifie que var sert le but de déclarer une variable qui est local à l'étendue dans laquelle elle est déclarée. Si la variable n'est pas associée à un mot-clé var, alors la variable est déclarée dans une portée globale. Dans le cas de la création d'une boucle de récursivité, vous devrez utiliser le mot clé var pour tous les cas, sinon, il pourrait y avoir une corruption des données. L'exemple suivant illustre comment inverser le contenu d'une pile utilisant la récursivité. Lorsque vous utilisez la récursivité, parfois vous devront déclarer des paramètres de fonction qui ne servent que comme valeurs de référence. Source: / website / ROOT / ajaxrecipes / javascript / fonction variablebehavior.html RecursiveStackOldWay (arrayToProcess, processedArray) (info ( "RecursiveStackOldWay", "---> Start "); info (" RecursiveStackOldWay "," profondeur recursive = "+ (processedArray. longueur + 1)); processedArray.push (arrayToProcess.pop ()); if (arrayToProcess.length> 0) (RecursiveStackOldWay (arrayToProcess, processedArray);) info ( "RecursiveStackOldWay", "---> End ");) arrayToProcess var = new Array (); arrayToProcess.push ( "value1"); arrayToProcess.push ( "value2"); processedArray var = new Array () RecursiveOldWayStack (arrayToProcess, processedArray); Ici, la fonction RecursiveStackOldWay a deux paramètres: arrayToProcess et processedArray. Le premier paramètre, arrayToProcess, est le tableau qui sera inversée. Le deuxième paramètre, processedArray, est la destination pile. La pile de destination doit être traîné comme un paramètre pour chaque récurrence, de sorte que la fonction peut mettre la pile quelque part. L'appelant est responsable de l'instanciation de la pile de destination et de la transmettre à la fonction récursive. Souvent, cependant, lors de la création des fonctions récursives , vous devrez appeler la fonction avec certains paramètres qui sont définis dans le top à première demande niveau. Ces paramètres n'ont rien à voir avec l'appel initial, pourtant le premier top-niveau d'appel a besoin de les déclarer (processedArray). En un mot, le problème est que lorsque vous appelez une fonction récursive, vous avez besoin d'initialiser un ensemble de variables qui sont ensuite utilisés par la récursivité. Dans l'exemple, l'initialisation est une responsabilité de l'appelant. Les travaux de solution, mais il est loin d'être optimal, parce que le développeur a besoin de comprendre comment certains paramètres de fonction, même si elles ne seront pas utilisés par l'appelant. Une autre solution est de créer une fonction wrapper pour la récursivité qui initialise les paramètres, puis appelle la récursivité. La fonction wrapper va fonctionner, mais maintenant, le programmeur doit conserver la fonction de récursivité et la fonction wrapper. JavaScript propose une troisième solution: laisser la fonction de récursivité s'initialiser. La question est, comment la fonction de récursivité sais qu'il est appelé pour la première fois? Dans un langage de programmation traditionnels comme Java ou C #, un paramètre booléen serait définie et réglé à true pour indiquer que le premier appel, et faux d'indiquer tout appel ultérieur. La solution JavaScript ne nécessitent pas un drapeau ou un indicateur, car les paramètres sont eux-mêmes indicateurs. Par exemple, imaginons que la fonction d'implémentation RecursiveOldWayStack reste tel quel et le code qui appelle RecursiveOldWayStack ressemble au suivant: arrayToProcess var = new Array (); arrayToProcess.push ( "value1"); arrayToProcess.push ( "value2"); processedArray var = RecursiveOldWayStack (arrayToProcess); Dans la mise en œuvre de modification, l'appelant n'est pas responsable de l'instanciation de la pile de destination. Cette responsabilité a été déléguée à la fonction RecursiveOldWayStack. Cependant, un problème se pose parce que RecursiveOldWayStack a besoin d'initialiser et de commencer la récursivité. La solution employée par JavaScript est de déterminer si le second paramètre est défini, comme illustré dans la modification de la fonction suivante appelée RecursiveStack. Source: / website / ROOT / ajaxrecipes / javascript / fonction variablebehavior.html RecursiveStack (arrayToProcess, processedArray) (info ( "RecursiveStack", "---> Start "); if (typeof (processedArray) == "undefined") ( info ( "RecursiveStack», «initiale»); processedArray = new Array (); RecursiveStack (arrayToProcess, processedArray); info ( "RecursiveStack", "---> End "); retour processedArray; )else (info ( "RecursiveStack", "Recursive profondeur =" + (processedArray.length + 1)); processedArray.push (arrayToProcess.pop ()); if (arrayToProcess.length> 0) (RecursiveStack (arrayToProcess, processedArray); ) info ( "RecursiveStack", "---> End "); return;)) Dans la mise en œuvre de modification, la fonction RecursiveStack met en œuvre une attente. L'idée est que si la fonction est appelée avec un seul paramètre, il est alors un interlocuteur faire le premier appel de la récursivité, sinon, une récurrence qui se passe. L'attente de savoir si un premier appel qui se passe est déterminée par le code en caractères gras. Si le deuxième paramètre, processedArray, n'est pas défini, alors la fonction récursive s'initialise et démarre la récursivité. Si le deuxième paramètre est défini, alors il est supposé une récursion qui se passe, et la fonction de traiter les données comme telles. Avant de continuer, vous pourriez avoir capturé le fait que RecursiveStack a deux paramètres, mais elle est appelée avec un. Plus tôt, j'ai parlé des attentes et que l'appelant a besoin de passer deux paramètres. Cet exemple ne dit pas que l'appelant n'a pas besoin de passer deux paramètres, mais plutôt l'exemple dit que si l'appelant ne passe pas deux paramètres, la fonction a la capacité de compenser. La même fonction peut être utilisée pour l'initialisation et récursivité basée sur l'attente. Si, toutefois, un interlocuteur définit le second paramètre, cela signifie que l'appelant a pris la responsabilité de mettre en œuvre l'initialisation. Avec un interlocuteur défini par l'initialisation, RecursiveStack seront pas effectuer une initialisation et sauter directement à la fonctionnalité récursivité. L'avantage de cette solution est que vous avez une fonction polyvalente sans avoir à définir explicitement une fonction wrapper. Vous mai-être: «Bien sûr, cela est possible en utilisant un langage tel que Java ou C # en utilisant les fonctions surchargées." Oui, c'est possible en utilisant les fonctions surchargées, mais comme mentionné précédemment, une fonction surchargée est une fonction wrapper qui appelle la mise en œuvre effective , ce qui signifie deux fonctions doivent être écrites et maintenues. En JavaScript, tout peut être enveloppé dans une fonction autonome. Maintenant que vous avez mis en place la récursivité et connaître la différence entre une variable de portée locale et une variable de portée mondiale, la prochaine question est, ce qui arrive s'il ya deux variables avec le même nom? Imaginez la définition d'une variable à une portée locale qui existe dans une dimension mondiale ce qui arrive aux niveaux mondial et local portée des déclarations de variables? Le code suivant montre comment une variable est définie globalement dans une fonction et ensuite référencé dans une autre fonction. Source: / website / ROOT / ajaxrecipes / javascript / fonction variablebehavior.html GlobalScope () (info ( "GlobalScope (scopedVariable)", typeof (scopedVariable)); scopedVariable = "Globalscope"; info ( "GlobalScope (scopedVariable)", "scopedVariable =" + + scopedVariable ➥ "type =" + typeof (scopedVariable));) function testScope () (info ( "OtherScope (scopedVariable)", "scopedVariable = "+ scopedVariable + "Type =" ➥ + typeof (scopedVariable));) scopedVariable est défini dans GlobalScope et référencées dans testScope. Puisqu'il n'y a pas var basé sur déclaration de scopedVariable dans GlobalScope, scopedVariable est mis dans la portée globale. Running testScope après GlobalScope entraînera scopedVariable être définies globalement, comme indiqué dans la sortie généré suivant: Info: GlobalScope () scopedVariable undefined Info: GlobalToLocalScope (scopedVariable) scopedVariable type = globalscope = Info phrase: testScope scopedVariable () scopedVariable type = globalscope = string Dans la sortie généré, GlobalScope est appelé, et au début de la mise en oeuvre de fonction, scopedVariable est indéfini. Puis scopedVariable se voit attribuer un tampon, et le résultat généré indique que scopedVariable n'est pas undefined et les références d'une chaîne. Calling testScope montre que scopedVariable est global et se voit attribuer un tampon. Considérons maintenant le même exemple, à l'exception d'une variable au niveau mondial est portée comme une redéclarée variable locale en utilisant le mot-clé var. Source: / website / ROOT / ajaxrecipes / javascript / fonction variablebehavior.html AlwaysLocalScope () (info ( "GlobalToLocalScope (scopedVariable)", typeof (scopedVariable)); scopedVariable = "AlwaysLocalScope"; info ( "GlobalToLocalScope (scopedVariable)", "scopedVariable = "+ + scopedVariable ➥" type = "+ typeof (scopedVariable)); var scopedVariable;) Dans l'implémentation de la fonction, scopedVariable est d'abord affecté un tampon qui n'utilise pas le mot clé var. Ainsi, scopedVariable est déclarée au niveau de la portée mondiale. Ou du moins c'est ce que vous êtes amené à le croire. Ce qui arrive est que la variable est déclarée au niveau local parce que la dernière instruction de la fonction (en gras) déclare la variable scopedVariable d'être locale. Elle mai sembler étrange qu'une variable est déclarée comme étant local, si quelque part dans la fonction du Var mot-clé est utilisé. Cela devient encore plus étrange, car si le mot-clé var est utilisé dans un bloc de décision qui n'est jamais exécutée, la variable est toujours déclarées locales. Afin d'illustrer, d'abord la fonction est appelée AlwaysLocal puis testScope, qui génère la sortie suivante: Info: AlwaysLocalScope () scopedVariable undefined Info: AlwaysLocalScope (scopedVariable) scopedVariable = = AlwaysLocalScope Warn type de chaîne: Erreur générale (scopedVariable n'est pas définie) Lorsque la fonction AlwaysLocalScope est appelée, scopedVariable sera pas défini, ce qui signifie qu'il existe dans la portée ni globale ni locale. Puis, lorsque la variable est assignée, la sortie générée aura une valeur et son type. Lorsque la fonction testScope est appelée, une exception est soulevée en raison scopedVariable n'est pas définie. Maintenant, vous savez quand une variable est déclarée dans la portée globale et de portée locale. Le dernier test est de voir ce qui arrive quand une variable est déclarée tant au niveau global et la portée locale. Le test consiste à appeler les fonctions de la séquence: GlobalScope, testScope, AlwaysLocalScope, puis testScope. L'appel de cette séquence génère la sortie suivante: Info: GlobalScope () scopedVariable undefined Info: GlobalScope (scopedVariable) scopedVariable type = globalscope = Info phrase: testScope scopedVariable () scopedVariable type = globalscope = Info phrase: AlwaysLocalScope () scopedVariable undefined Info: AlwaysLocalScope (scopedVariable) scopedVariable = AlwaysLocalScope type string Info: testScope scopedVariable () scopedVariable type = globalscope = string Dans la sortie généré, scopedVariable est déclarée et affectées GlobalScope. La fonction testScope vérifie que scopedVariable existe. Puis, lors de l'appel AlwaysLocalScope, var déclare que toute référence à scopedVariable sein de la fonction est une variable de référence local. Ainsi, si il ya une variable définie au niveau mondial avec le même nom, il n'est pas accessible dans le cadre de la fonction. Vous avez deux façons pour faire référence à une variable globale: Référencement via la propriété fenêtre ou la création d'une fonction qui est externe à la fonction d'exécution (ce qui signifie que ce n'est pas une fonction inline) et assigner la variable globalement portée. Lorsqu'une variable n'est pas affecté, le typeof renvoie undefined function. Une fois que vous assignez une variable, typeof reviendra une autre valeur. Si une variable est définie dans le cadre d'une fonction, puis chaque fois que la fonction est appelée, la variable avant d'être assigné sera indéfini. Au niveau mondial, une variable peut être désactivé en utilisant l'opérateur delete, comme suit: Supprimer scopedVariable; Habituellement, l'opérateur delete est utilisé pour réinitialiser la propriété d'un objet. Quand supprimer est utilisé avec un identifiant, une référence de variable globale est supprimé. Vous ne pouvez pas supprimer une référence à une fonction en utilisant supprimer. Testons une autre variation du champ d'application en utilisant le code dynamique. En JavaScript, en utilisant la fonction eval exécutera un tampon JavaScript, qui teste si une variable sera considérée comme une portée globale et, quand il sera considéré comme une portée locale. La fonction AlwaysLocalScope sera donc modifié. Pour la première variante, AlwaysLocalScope aura une affectation dynamique: AlwaysLocalScope fonction () (info ( "AlwaysLocalScope (scopedVariable)", typeof (scopedVariable)); eval ( "scopedVariable = 'AlwaysLocalScope'");info ( "AlwaysLocalScope (scopedVariable)", "scopedVariable =" + + scopedVariable ➥ "type =" + typeof (scopedVariable)); scopedVariable var;) Le code modifié est indiqué en caractères gras, et l'attribution des scopedVariable est exécutée. Utilisant eval de cette manière n'a pas d'effet, et l'exécution dynamique du code est le même que si le code n'a pas été modifié. L'avantage avec eval est que vous pouvez attribuer un morceau de code dans une mémoire tampon de texte, puis exécuter ce tampon. La portée de scopedVariable n'a pas changé parce que le mot var existe encore dans la déclaration de fonction. La déclaration Une fois distribuée par le processeur JavaScript donnera lieu à une déclaration de variable locale. Une façon de modifier le comportement déclaration locale est d'intégrer la déclaration de variable dans une instruction eval, comme indiqué dans la modification du code suivant: AlwaysLocalScope fonction () (info ( "AlwaysLocalScope (scopedVariable)", typeof (scopedVariable)); eval ( "scopedVariable = 'AlwaysLocalScope'");info ( "AlwaysLocalScope (scopedVariable)", "scopedVariable =" + + scopedVariable ➥ "type =" + typeof (scopedVariable)); eval ( "scopedVariable var;");) Le code modifié par rapport au code original AlwaysLocalScope est en gras. Cette fois, la cession et la déclaration de scopedVariable sont dynamiques, ce qui signifie que lorsque scopedVariable attribué sera traité comme une variable globale. En effet, lorsque l'instruction eval premier est exécuté, il n'y a aucune déclaration de scopedVariable, et le runtime JavaScript va stocker scopedVariable dans l'espace mondial. Pour modifier le comportement et déclarer scopedVariable comme une variable locale, AlwaysLocalScope doit être modifiée une fois de plus , comme suit: AlwaysLocalScope fonction () (info ( "AlwaysLocalScope (scopedVariable)", typeof (scopedVariable)); eval ( "scopedVariable var;"); eval ( "scopedVariable = 'AlwaysLocalScope'");info ( "AlwaysLocalScope (scopedVariable)", "scopedVariable =" + + scopedVariable ➥ "type =" + typeof (scopedVariable));) Lors de la dernière modification, le eval première est la déclaration de scopedVariable aide du mot clé var. Le premier appel résultats eval dans la déclaration de scopedVariable comme une variable locale. L'appel eval seconde assigne une valeur à scopedVariable, qui est portée comme une variable locale. Lorsque la déclaration de variables dans le cadre de fonctions ou dans la portée globale, gardez les points suivants à l'esprit: • Il ya deux champs d'application à une variable: locale à une fonction et mondial. • Une variable locale est déclarée en utilisant le mot-clé var, à l'exception étant l'utilisation du var dans un contexte mondial. L'utilisation du Var n'a pas besoin d'être au début d'une fonction. • Une variable globale est déclarée quand une variable est attribué sans utiliser le mot-clé var. • Il est bon de déclarer des variables au niveau de la portée mondiale en utilisant le mot-clé var. • Collectivités locales et les variables globales avec le même nom ne pas écraser l'autre. Un cache localement variable déclarée globalement déclaré une variable avec le même nom. • Quand une variable n'est pas déclaré, en utilisant typeof sur les résultats variable non définie. • Vous pouvez effacer les variables globales en utilisant l'opérateur delete. • Lorsque vous utilisez les fonctions récursives, vous devez utiliser localement les variables déclarées. • La récursivité implique généralement une initialisation et une exécution. En utilisant JavaScript, l'initialisation et l'exécution peut être enveloppé dans une seule fonction. • initialisation d'emballage et de l'exécution dans une seule fonction utilise des attentes, où la disponibilité des variables est testée pour déterminer un contexte d'appel. • Il est possible d'utiliser eval pour déclarer dynamiquement des variables locales ou globales. Eval • Utilisation amènera le processeur à exécuter JavaScript n'est pas un look-ahead lors de l'identification des variables locales. Ainsi, pour déclarer une variable locale, le mot clé var doit être utilisé avant d'assigner une variable. • Utilisation de l'instruction EVAL, un programme pourrait déterminer de façon dynamique ou non d'une variable doit être déclaré à la portée locale ou de la portée mondiale. un article présenté par Sonja Lande Disclaimer:Notre site n'est pas responsable du contenu de cet article. Webarticles est une ressource d'information gratuite. Important: Cet article «Comprendre le comportement des variables Lorsqu'ils transposent la récursivité" a été traduit par un logiciel automatique. Nous nous sentons désolés pour les fautes d'orthographe que mai ont eu lieu. Nous vous remercions de votre compréhension.
|
|||||
| Online: 334 users browsing the articles directory |
|
|