Surpris que la variable globale ait une valeur indéfinie en JavaScript

Aujourd'hui, j'ai été complètement surpris quand j'ai vu qu'une variable globale avait une valeur undefined dans certains cas.

Exemple:

 var value = 10; function test() { //A console.log(value); var value = 20; //B console.log(value); } test(); 

Donne la sortie comme

 undefined 20 

Ici, pourquoi le moteur de JavaScript considère la valeur globale comme undefined . Je sais que JavaScript est une langue interprétée. Comment peut-on considérer les variables dans la fonction?

Est-ce un piège du moteur de JavaScript?

Ce phénomène est connu sous le nom de: levage variable JavaScript .

En aucun cas, vous n'atteignez la variable globale dans votre fonction; Vous n'allez jamais accéder à la variable de value locale.

Votre code équivaut à ce qui suit:

 var value = 10; function test() { var value; console.log(value); value = 20; console.log(value); } test(); 

Toujours surpris de ne undefined être undefined ?


Explication:

C'est quelque chose que chaque programmeur JavaScript se heurte tôt ou tard. Autrement dit, quelles que soient les variables que vous déclarez sont toujours hissées au sommet de votre fermeture locale. Donc, même si vous avez déclaré votre variable après le premier appel console.log , il est toujours considéré comme si vous l'aviez déclaré avant cela.
Toutefois, seule la partie de la déclaration est hissée; La mission, d'autre part, n'est pas.

Donc, lorsque vous avez appelé la console.log(value) , vous console.log(value) référence à votre variable déclarée localement, qui n'a encore rien à lui attribuer; Donc undefined .

Voici un autre exemple :

 var test = 'start'; function end() { test = 'end'; var test = 'local'; } end(); alert(test); 

Que pensez-vous que cela va alerter? Non, ne lisez pas simplement, pensez-y. Quelle est la valeur du test ?

Si vous avez dit autre chose que de start , vous avez eu tort. Le code ci-dessus est équivalent à ceci:

 var test = 'start'; function end() { var test; test = 'end'; test = 'local'; } end(); alert(test); 

Afin que la variable globale ne soit jamais affectée.

Comme vous pouvez le voir, peu importe où vous mettez votre déclaration de variable, il est toujours hissé au sommet de votre fermeture locale.


Note latérale:

Cela s'applique également aux fonctions.

Considérez ce code :

 test("Won't work!"); test = function(text) { alert(text); } 

Qui vous donnera une erreur de référence:

Uncaught ReferenceError: le test n'est pas défini

Cela lève beaucoup de développeurs, puisque ce code fonctionne bien:

 test("Works!"); function test(text) { alert(text); } 

La raison de cela, comme indiqué, est que la partie d'affectation n'est pas hissée. Ainsi, dans le premier exemple, lorsque le test("Won't work!") été exécuté, la variable de test a déjà été déclarée, mais n'a pas encore affecté la fonction.

Dans le deuxième exemple, nous n'utilisons pas d'affectation variable. Plutôt, nous utilisons une syntaxe de déclaration de fonction appropriée, ce qui permet d' obtenir la fonction complètement hissée.


Ben Cherry a écrit un excellent article sur ce sujet, intitulé correctement Scoping et Hoisting JavaScript .
Lis le. Il vous donnera toute l'image en détail.

J'ai été quelque peu déçu que le problème ici soit expliqué, mais personne n'a proposé une solution. Si vous souhaitez accéder à une variable globale dans la portée de la fonction sans que la fonction ne window.varName une var locale indéfinie, faites référence à la var comme window.varName

Les variables dans JavaScript ont toujours une portée de toute la fonction. Même s'ils ont été définis au milieu de la fonction, ils sont visibles avant. Des phénomènes similaires peuvent être observés avec la fonction de levage.

Cela étant dit, la première console.log(value) voit la variable de value (l'intérieur qui ombre la value externe), mais elle n'a pas encore été initialisée. Vous pouvez le penser comme si toutes les déclarations de variables étaient implicitement déplacées au début de la fonction ( pas le plus grand bloc de code interne), tandis que les définitions sont laissées au même endroit.

Voir également

  • Fonction Javascript fonctionnant et hissant
  • Déclarations de variable Javascript en tête d'une fonction

Il existe une value variable value , mais lorsque le contrôle entre dans la fonction de test , une autre variable de value est déclarée, ce qui représente l'image globale. Étant donné que les déclarations de variables ( mais pas les affectations ) en JavaScript sont hiérisées au sommet de la portée dans laquelle elles sont déclarées:

 //value == undefined (global) var value = 10; //value == 10 (global) function test() { //value == undefined (local) var value = 20; //value == 20 (local) } //value == 10 (global) 

Notez qu'il en va de même pour les déclarations de fonction, ce qui signifie que vous pouvez appeler une fonction avant qu'elle ne soit définie dans votre code:

 test(); //Call the function before it appears in the source function test() { //Do stuff } 

Il est également intéressant de noter que lorsque vous combinez les deux en une expression de fonction, la variable sera undefined jusqu'à ce que l'affectation ait lieu, de sorte que vous ne pouvez pas appeler la fonction jusqu'à ce que cela se produise:

 var test = function() { //Do stuff }; test(); //Have to call the function after the assignment