Quelle est la portée des variables dans JavaScript?

Quelle est la portée des variables dans javascript? Ont-ils la même portée à l'intérieur qu'à l'extérieur d'une fonction? Ou faut-il le même problème? En outre, Où sont stockées les variables si elles sont définies globalement?

1755
demandé sur John Slegers 2009-02-01 11:27:19
la source

26 ответов

je pense que le mieux que je puisse faire est de vous donner un tas d'exemples à étudier. Les programmeurs Javascript sont pratiquement classés selon leur compréhension de la portée. Il peut parfois être très contre-intuitif.

  1. a variable de portée mondiale

    // global scope
    var a = 1;
    
    function one() {
      alert(a); // alerts '1'
    }
    
  2. Locale

    // global scope
    var a = 1;
    
    function two(a) { // passing (a) makes it local scope
      alert(a); // alerts the given argument, not the global value of '1'
    }
    
    // local scope again
    function three() {
      var a = 3;
      alert(a); // alerts '3'
    }
    
  3. Intermédiaire : Pas une telle chose comme le bloc de portée en JavaScript (ES5; ES6 introduit let )

    un.

    var a = 1;
    
    function four() {
      if (true) {
        var a = 4;
      }
    
      alert(a); // alerts '4', not the global value of '1'
    }
    

    B.

    var a = 1;
    
    function one() {
      if (true) {
        let a = 4;
      }
    
      alert(a); // alerts '1' because the 'let' keyword uses block scoping
    }
    
  4. Intermédiaire : propriétés de l'Objet

    var a = 1;
    
    function Five() {
      this.a = 5;
    }
    
    alert(new Five().a); // alerts '5'
    
  5. Avancé : Fermeture

    var a = 1;
    
    var six = (function() {
      var a = 6;
    
      return function() {
        // JavaScript "closure" means I have access to 'a' in here,
        // because it is defined in the function in which I was defined.
        alert(a); // alerts '6'
      };
    })();
    
  6. Avancé : basé sur des Prototypes de résolution de portée

    var a = 1;
    
    function seven() {
      this.a = 7;
    }
    
    // [object].prototype.property loses to
    // [object].property in the lookup chain. For example...
    
    // Won't get reached, because 'a' is set in the constructor above.
    seven.prototype.a = -1;
    
    // Will get reached, even though 'b' is NOT set in the constructor.
    seven.prototype.b = 8;
    
    alert(new seven().a); // alerts '7'
    alert(new seven().b); // alerts '8'
    

  7. Global+Local : Un supplément de Cas complexes

    var x = 5;
    
    (function () {
        console.log(x);
        var x = 10;
        console.log(x); 
    })();
    

    This imprimera undefined et 10 plutôt que 5 et 10 car JavaScript déplace toujours les déclarations variables (pas les initialisations) vers le haut de la portée, ce qui rend le code équivalent à:

    var x = 5;
    
    (function () {
        var x;
        console.log(x);
        x = 10;
        console.log(x); 
    })();
    
  8. clause Catch d'étendue variable

    var e = 5;
    console.log(e);
    try {
        throw 6;
    } catch (e) {
        console.log(e);
    }
    console.log(e);
    

    ce sera imprimé 5 , 6 , 5 . À l'intérieur de la clause de sauvegarde e les ombres des variables globales et locales. Mais cette portée spéciale ne s'applique qu'à la variable capturée. Si vous écrivez var f; dans la clause catch, alors c'est exactement la même chose que si vous l'aviez définie avant ou après le bloc try-catch.

2305
répondu Triptych 2018-08-20 13:07:51
la source

Javascript utilise des chaînes de portée pour établir la portée d'une fonction donnée. Il y a généralement une portée globale, et chaque fonction a son propre imbriquée portée. Toute fonction définie dans une autre fonction a une portée locale qui est liée à la fonction externe. C'est toujours la position dans la source qui définit la portée.

un élément de la chaîne scope est essentiellement une carte avec un pointeur vers son scope parent.

lors de la résolution d'un variable, javascript commence au niveau le plus proche et recherche vers l'extérieur.

222
répondu krosenvold 2012-08-14 11:54:06
la source

les Variables déclarées globalement ont une portée globale. Les Variables déclarées dans une fonction sont scopées à cette fonction, et les variables globales de l'ombre du même nom.

(je suis sûr qu'il y a beaucoup de subtilités que les vrais programmeurs JavaScript seront en mesure de souligner dans d'autres réponses. En particulier, je suis tombé sur cette page sur ce que signifie exactement this à tout moment. Avec un peu de chance ce lien plus introductif est assez pour vous obtenir a commencé.)

96
répondu Jon Skeet 2014-02-25 22:12:12
la source

Old school JavaScript

traditionnellement, le JavaScript n'a que deux types de portée :

  1. global Scope : les Variables sont connues tout au long de l'application, dès le début de l'application (*)
  2. portée fonctionnelle : les Variables sont connues dans la fonction ils sont déclarés dans, dès le début de la fonction (*)

Je ne m'étendrai pas là-dessus, car il y a déjà beaucoup d'autres réponses expliquant la différence.


Moderne JavaScript

le spécifications JavaScript les plus récentes permettent maintenant aussi une troisième portée:

  1. champ D'application du bloc : les Variables sont connues sous le nom de le bloc elles sont déclarées à partir du moment où elles sont déclarées (**)

comment créer des variables de champ de bloc?

traditionnellement, vous créez vos variables comme ceci:

var myVariable = "Some text";

champ D'application du bloc les variables sont créées comme ceci:

let myVariable = "Some text";

Quelle est donc la différence entre la portée fonctionnelle et la portée globale?

pour comprendre la différence entre la portée fonctionnelle et la portée de bloc, considérons le code suivant :

// i IS NOT known here
// j IS NOT known here
// k IS known here, but undefined
// l IS NOT known here

function loop(arr) {
    // i IS known here, but undefined
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here

    for( var i = 0; i < arr.length; i++ ) {
        // i IS known here, and has a value
        // j IS NOT known here
        // k IS known here, but has a value only the second time loop is called
        // l IS NOT known here
    };

    // i IS known here, and has a value
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here

    for( let j = 0; j < arr.length; j++ ) {
        // i IS known here, and has a value
        // j IS known here, and has a value
        // k IS known here, but has a value only the second time loop is called
        // l IS NOT known here
    };

    // i IS known here, and has a value
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here
}

loop([1,2,3,4]);

for( var k = 0; k < arr.length; k++ ) {
    // i IS NOT known here
    // j IS NOT known here
    // k IS known here, and has a value
    // l IS NOT known here
};

for( let l = 0; l < arr.length; l++ ) {
    // i IS NOT known here
    // j IS NOT known here
    // k IS known here, and has a value
    // l IS known here, and has a value
};

loop([1,2,3,4]);

// i IS NOT known here
// j IS NOT known here
// k IS known here, and has a value
// l IS NOT known here

ici, nous pouvons voir que notre variable j est seulement connu dans le premier pour boucle, mais pas avant et après. Pourtant, notre variable i est connu dans l'ensemble de la fonction.

aussi, considérer que les variables de bloc scoped ne sont pas connus avant qu'ils soient déclarés parce qu'ils ne sont pas hissés. Vous n'êtes pas non plus autorisé à faire une nouvelle sélection de la même variable à l'intérieur du même bloc. Cela rend les variables à portée de bloc moins sujettes aux erreurs que les variables à portée globale ou fonctionnelle, qui sont hissées et qui ne produisent pas d'erreurs dans le cas de déclarations multiples.


Est-il sécuritaire d'utiliser le bloc de portée des variables d'aujourd'hui?

qu'il soit sûr ou non d'utiliser aujourd'hui, dépend de votre environnement:

  • si vous écrivez un code JavaScript côté serveur ( noeud.js ), vous pouvez utiliser en toute sécurité la déclaration let .

  • si vous écrivez un code JavaScript côté client et utilisez un transpirateur (comme Traceur ), vous pouvez utiliser en toute sécurité la déclaration let , mais votre code est susceptible d'être tout sauf optimal en ce qui concerne la performance.

  • si vous écrivez du code JavaScript côté client et que vous n'utilisez pas de transpirateur, vous devez considérer le support du navigateur.

    Aujourd'hui, 23 février 2016, ce sont certains navigateurs qui ne prennent pas en charge let ou n'ont qu'un soutien partiel:

    • Internet explorer 10 et en dessous (pas de support)
    • Firefox 43 et en dessous (pas de support)
    • Safari 9 et en dessous (pas de support)
    • Opera Mini 8 et en dessous (pas de support)
    • navigateur Android 4 et ci-dessous (sans support)
    • Opéra 36 et ci-dessous (prise en charge partielle)
    • Chome 51 et ci-dessous (prise en charge partielle)

enter image description here


Comment garder une trace de la prise en charge du navigateur

pour un aperçu actualisé dont les navigateurs prennent en charge la déclaration let au moment de la lecture de cette réponse, voir cette Can I Use page .


(*) les variables globales et fonctionnelles peuvent être initialisées et utilisées avant d'être déclarées car les variables JavaScript sont hissées . Cela signifie que les déclarations sont toujours bien au-dessus de la portée.

(**) les variables à portée de bloc ne sont pas hissées

57
répondu John Slegers 2018-03-07 01:25:33
la source

voici un exemple:

<script>

var globalVariable = 7; //==window.globalVariable

function aGlobal( param ) { //==window.aGlobal(); 
                            //param is only accessible in this function
  var scopedToFunction = {
    //can't be accessed outside of this function

    nested : 3 //accessible by: scopedToFunction.nested
  };

  anotherGlobal = {
    //global because there's no `var`
  }; 

}

</script>

vous voudrez enquêter sur les fermetures, et comment les utiliser pour faire private members .

35
répondu geowa4 2009-02-01 11:48:09
la source

la clé, telle que je la comprends, est que Javascript a la détermination de la portée au niveau de la fonction par rapport au bloc C le plus commun.

Voici un bon article sur le sujet.

28
répondu James McMahon 2012-05-15 21:38:30
la source

dans "Javascript 1.7" (extension de Mozilla à Javascript) on peut aussi déclarer des variables de block-scope avec let statement :

 var a = 4;
 let (a = 3) {
   alert(a); // 3
 }
 alert(a);   // 4
23
répondu kennytm 2010-04-06 15:19:39
la source

l'idée d'établir la portée en JavaScript lorsqu'elle a été conçue à l'origine par Brendan Eich vient du HyperCard langage de script HyperTalk .

dans cette langue, les affichages étaient semblables à une pile de cartes index. Il y avait une carte maîtresse appelée background. Il était transparent et peut être vu comme la carte du bas. Tout le contenu de cette carte de base a été partagé avec les cartes placées sur haut de il. Chaque carte placée sur le dessus avait son propre contenu qui a pris la priorité sur la carte précédente, mais avait tout de même accès aux cartes précédentes si vous le souhaitez.

C'est exactement comme cela que le système JavaScript scoping est conçu. Il a juste des noms différents. Les cartes en JavaScript sont connues sous le nom de contextes D'exécution ECMA . Chacun de ces contextes contient trois parties principales. Un environnement variable, un environnement lexical, et cette liaison. Pour en revenir à la référence cards, l'environnement lexical contient tout le contenu des cartes précédentes en bas de la pile. Le contexte actuel est en haut de la pile et tout contenu déclaré sera stocké dans l'environnement variable. L'environnement variable aura préséance en cas de collision nommante.

cette reliure indiquera l'objet contenant. Parfois les portées ou les contextes d'exécution changent sans que l'objet contenant change, comme dans une fonction déclarée où l'objet contenant peut être window ou une fonction de constructeur.

ces contextes d'exécution sont créés à tout moment. Le contrôle est transféré lorsque le code commence à s'exécuter, et cela se fait principalement à partir de l'exécution de la fonction.

telle est donc l'explication technique. En pratique, il est important de se rappeler que dans JavaScript

  • les portées sont techniquement des "contextes D'exécution"
  • les contextes forment une pile d'environnements où les variables sont stockées
  • le haut de la pile a priorité (le bas étant le contexte global)
  • chaque fonction crée un contexte d'exécution (mais pas toujours nouveau)

application à l'un des exemples précédents (5. "Fermeture") sur cette page, c'est possibilité de suivre la pile de contextes d'exécution. Dans cet exemple, il y a trois contextes dans la pile. Ils sont définis par le contexte externe, le contexte dans la fonction immédiatement invoquée appelée par var six, et le contexte dans la fonction retournée à l'intérieur de la fonction immédiatement invoquée de var six.

je ) à L'extérieur du contexte. Il a un environnement variable d'un = 1

ii ) le contexte IIFE, il a un environnement lexical de a = 1, mais un environnement variable de a = 6 qui a priorité dans la pile

iii ) le contexte de la fonction retournée, il a un environnement lexical de a = 6 et c'est la valeur référencée dans l'alerte lorsqu'elle est appelée.

enter image description here

18
répondu Travis J 2015-09-14 23:29:53
la source

1) Il y a un champ d'Application global, un champ d'application de fonction, et le champ d'application with ET catch. Il n'y a pas de portée de niveau' block ' en général pour les variables -- les instructions with et catch ajoutent des noms à leurs blocks.

2) les portées sont imbriquées par des fonctions jusqu'à la portée globale.

3) Les propriétés sont résolues en passant par la chaîne du prototype. L'instruction apporte de la propriété de l'objet de noms dans la portée lexicale définie par le bloc.

EDIT: ECMAAScript 6 (Harmony) est spécifié pour supporter let, et je sais que chrome permet un drapeau 'harmony', donc peut-être qu'il le supporte..

Laissez serait un support pour bloc de portée au niveau, mais vous devez utiliser le mot clé pour y arriver.

EDIT: Basé sur Benjamin de pointage de la avec et instructions catch dans les commentaires, j'ai édité le post, et a ajouté plus. Les deux la avec et les instructions catch introduire des variables dans leurs blocs respectifs, et que est une portée de bloc. Ces variables sont aliasées aux propriétés des objets qui y sont passés.

 //chrome (v8)

 var a = { 'test1':'test1val' }
 test1   // error not defined
 with (a) { var test1 = 'replaced' }
 test1   // undefined
 a       // a.test1 = 'replaced'

EDIT: Clarifier exemple:

test 1 est scopé au bloc avec, mais est aliasé au bloc A. test 1. 'Var test1' crée une nouvelle variable test1 dans le contexte lexical supérieur (fonction, ou global), à moins qu'elle ne soit une propriété d'un -- ce qu'elle est.

Beurk! Être attention en utilisant 'with' -- tout comme var est un noop si la variable est déjà définie dans la fonction, c'est aussi un noop en ce qui concerne les noms importés de l'objet! Un petit avertissement sur le nom déjà défini rendrait cela beaucoup plus sûr. Personnellement, je ne m'en servirai jamais à cause de ça.

16
répondu Gerard ONeill 2014-06-06 21:13:06
la source

j'ai trouvé que beaucoup de gens nouveaux à JavaScript ont du mal à comprendre que l'héritage est disponible par défaut dans le langage et que la portée de la fonction est la seule portée, jusqu'à présent. J'ai fourni une extension à un plus beau que j'ai écrit à la fin de l'année dernière appelé JSPretty. La fonctionnalité couleurs Fonction portée dans le code et associe toujours une couleur à toutes les variables déclarées dans cette portée. La fermeture est visuellement démontrée quand une variable avec une couleur d'une portée est utilisée dans un différent portée.

Essayez de la fonction:

voir une démo à:

visualiser le code:

actuellement, la fonctionnalité offre un support pour une profondeur de 16 fonctions imbriquées, mais ne colore pas les variables globales.

9
répondu austincheney 2013-03-21 21:31:11
la source

JavaScript n'ont que deux type de portée :

  1. de Portée Mondiale : Global n'est rien mais une fenêtre au niveau de la portée.Ici, variable présente tout au long de l'application.
  2. portée fonctionnelle : Variable déclarée dans une fonction avec var le mot-clé a une portée fonctionnelle.

chaque fois qu'une fonction est appelée, une portée variable objet est créé (et inclus dans la chaîne scope) qui est suivi de variables en JavaScript.

        a = "global";
         function outer(){ 
              b = "local";
              console.log(a+b); //"globallocal"
         }
outer();

la Portée de la chaîne -->

  1. niveau de fenêtre - a et outer fonction sont au niveau supérieur dans la chaîne de portée.
  2. lorsque la fonction externe appelle un nouveau variable scope object (et inclus dans la chaîne scope) ajouté avec la variable b à l'intérieur.

maintenant quand un la variable a a exigé qu'il cherche d'abord pour la variable portée la plus proche et si la variable n'est pas là qu'il se déplace à l'objet suivant de la chaîne de portée variable.qui est dans ce cas est le niveau de la fenêtre.

8
répondu Anshul 2014-09-22 00:49:17
la source

juste pour ajouter aux autres réponses, scope est une liste de recherche de tous les identificateurs déclarés (variables), et applique un ensemble de règles strictes quant à la façon dont ceux-ci sont accessibles au code en cours d'exécution. Cette recherche peut avoir pour but d'attribuer à la variable, qui est une référence LHS (à gauche), ou elle peut avoir pour but de retrouver sa valeur, qui est une référence RHS (à droite). Ces recherches sont ce que le moteur JavaScript fait à l'interne quand il est compiler et exécuter le code.

donc, de ce point de vue, je pense qu'une image serait utile que j'ai trouvé dans les lunettes et les fermetures ebook par Kyle Simpson:

image

citant son ebook:

le bâtiment représente les règles de portée imbriquées de notre programme. Première étage du bâtiment représente votre champ d'application actuellement en cours d'exécution, où que vous soyez. Le niveau supérieur du bâtiment est à la portée globale. Vous résolvez les références LHS et RHS en regardant sur votre plancher actuel, et si vous ne le trouvez pas, prenez l'ascenseur à l'étage suivant, en regardant là, puis le suivant, et ainsi de suite. Une fois que vous obtenez à l'étage supérieur (la portée mondiale), soit vous trouver ce que vous cherchez, ou vous ne le fais pas. Mais tu dois arrêter de toute façon.

Une chose de la note qui vaut la peine de mentionner, "Champ de recherche s'arrête une fois qu'il trouve le premier match".

cette idée de" niveaux de portée "explique pourquoi" ceci " peut être changé avec une portée nouvellement créée, si elle est recherchée dans une fonction imbriquée. Voici un lien qui va dans tous ces détails, Tout ce que vous vouliez savoir à propos de JavaScript scope "151980920

8
répondu James Drinkard 2016-03-30 16:33:04
la source

lancez le code. espérons que cela donnera une idée sur l'étendue des

Name = 'global data';
document.Name = 'current document data';
(function(window,document){
var Name = 'local data';
var myObj = {
    Name: 'object data',
    f: function(){
        alert(this.Name);
    }
};

myObj.newFun = function(){
    alert(this.Name);
}

function testFun(){
    alert("Window Scope : " + window.Name + 
          "\nLocal Scope : " + Name + 
          "\nObject Scope : " + this.Name + 
          "\nCurrent document Scope : " + document.Name
         );
}


testFun.call(myObj);
})(window,document);
7
répondu Yeasin Abedin Siam 2014-10-18 13:54:56
la source

Portée Mondiale:

variables Globales sont exactement comme des stars mondiales (Jackie Chan, Nelson Mandela). Vous pouvez y accéder (obtenir ou définir la valeur), à partir de n'importe quelle partie de votre application. Les fonctions globales sont comme des événements globaux (Nouvel An, Noël). Vous pouvez les exécuter (appeler) à partir de n'importe quelle partie de votre application.

//global variable
var a = 2;

//global function
function b(){
   console.log(a);  //access global variable
}

Portée Locale :

si vous êtes aux Etats - Unis, vous connaissez peut-être Kim Kardashian, célèbre célébrité ( elle d'une manière ou d'une autre réussit à faire les tabloïds). Mais les gens en dehors des USA ne la reconnaîtront pas. Elle est une star locale, liée à son territoire.

les variables locales sont comme les étoiles locales. Vous ne pouvez y accéder (obtenir ou définir la valeur) qu'à l'intérieur du scope. Une fonction locale est comme des événements locaux - vous pouvez exécuter seulement (celebrate) à l'intérieur de cette portée. Si vous voulez y accéder depuis l'extérieur de la portée, vous obtiendrez une erreur de référence

function b(){
   var d = 21; //local variable
   console.log(d);

   function dog(){  console.log(a); }
     dog(); //execute local function
}

 console.log(d); //ReferenceError: dddddd is not defined    

Vérifiez cet article pour une compréhension approfondie de la portée

7
répondu KhanSharp 2016-02-23 21:56:04
la source

il n'y a presque que deux types de portées JavaScript:

  • le champ d'application de chaque déclaration var est associé à la fonction la plus immédiatement enveloppante
  • s'il n'y a pas de fonction enveloppante pour une déclaration var, c'est la portée globale

ainsi, les blocs autres que les fonctions ne créent pas une nouvelle portée. Cela explique pourquoi les for-loops écrasent les variables externes scopées:

var i = 10, v = 10;
for (var i = 0; i < 5; i++) { var v = 5; }
console.log(i, v);
// output 5 5

utilisant des fonctions à la place:

var i = 10, v = 10;
$.each([0, 1, 2, 3, 4], function(i) { var v = 5; });
console.log(i,v);
// output 10 10

dans le premier exemple, il n'y avait pas de champ d'application de bloc, de sorte que les variables initialement déclarées ont été écrasées. Dans le second exemple, il y avait une nouvelle portée due à la fonction, de sorte que les variables initialement déclarées étaient ombrées, et non écrasées.

C'est presque tout ce que vous devez savoir en termes de portée JavaScript, sauf:

donc vous pouvez voir que JavaScript scoping est en fait extrêmement simple, bien que pas toujours intuitif. Quelques éléments à prendre en compte:

    Les déclarations
  • var sont hissées au sommet de la portée. Cela signifie que peu importe où la déclaration var se produit, pour le compilateur c'est comme si le var lui-même se produit au sommet
  • plusieurs déclarations var dans le même champ d'application sont combinées

donc ce code:

var i = 1;
function abc() {
  i = 2;
  var i = 3;
}
console.log(i);     // outputs 1

est l'équivalent de:

var i = 1;
function abc() {
  var i;     // var declaration moved to the top of the scope
  i = 2;
  i = 3;     // the assignment stays where it is
}
console.log(i);

cela peut sembler contre-intuitif, mais il a du sens à partir de la point de vue d'un langage impératif designer.

5
répondu jackbean818 2015-10-29 19:12:19
la source

Moderne Js, ES6+, ' const " et " let '

vous devriez utiliser la détermination de la portée de bloc pour chaque variable que vous créez, tout comme la plupart des autres langues principales. var est obsolète . Cela rend votre code plus sûr et plus maintenable.

const doit être utilisé pour 95% des cas . Il le rend donc la variable référence ne peut pas changer. Tableau, les propriétés des objets et des noeuds DOM peuvent changer et devraient probablement être const .

let doit être utilisé pour toute variable devant être réaffectée. Ceci inclut dans une boucle for. Si vous changez de valeur au-delà de l'initialisation, utilisez let .

champ D'application de bloc signifie que la variable ne sera disponible que dans les parenthèses dans lesquelles elle est déclarée. Cela s'étend aux portées internes, y compris les fonctions anonymes créées dans votre portée.

5
répondu Gibolt 2017-12-08 22:03:40
la source

il n'y a que des portées de fonction dans JS. Ne pas bloquer les étendues! Vous pouvez voir ce qui hisse aussi.

var global_variable = "global_variable";
var hoisting_variable = "global_hoist";

// Global variables printed
console.log("global_scope: - global_variable: " + global_variable);
console.log("global_scope: - hoisting_variable: " + hoisting_variable);

if (true) {
    // The variable block will be global, on true condition.
    var block = "block";
}
console.log("global_scope: - block: " + block);

function local_function() {
    var local_variable = "local_variable";
    console.log("local_scope: - local_variable: " + local_variable);
    console.log("local_scope: - global_variable: " + global_variable);
    console.log("local_scope: - block: " + block);
    // The hoisting_variable is undefined at the moment.
    console.log("local_scope: - hoisting_variable: " + hoisting_variable);

    var hoisting_variable = "local_hoist";
    // The hoisting_variable is now set as a local one.
    console.log("local_scope: - hoisting_variable: " + hoisting_variable);
}

local_function();

// No variable in a separate function is visible into the global scope.
console.log("global_scope: - local_variable: " + local_variable);
4
répondu koredalin 2015-07-11 21:13:01
la source

chaque morceau de code JavaScript (global code ou fonctions) est associé à une chaîne scope. Ce champ d'application la chaîne est une liste ou une chaîne d'objets qui définit les variables qui sont dans la portée que code. Quand JavaScript doit chercher la valeur d'une variable x (un processus appelé résolution variable ), il commence par regarder le premier objet de la chaîne. Si cet objet a un bien nommé x , la valeur de ce bien est utilisé. Si le premier objet n'a pas une propriété nommée x , JavaScript continue la recherche avec l'objet suivant dans la chaîne. Si le second objet n'a pas de propriété nommée x , la recherche passe à la suivante objet, et ainsi de suite. Si x n'est la propriété d'aucun des objets de la chaîne scope, alors x n'entre pas dans le champ d'application de ce code, et une erreur de référence se produit. Dans le code JavaScript de haut niveau (c.-à-d., code Non contenu dans une fonction définition), la chaîne scope se compose d'un seul objet, l'objet global. Dans une fonction non imbriquée, la chaîne scope se compose de deux objets. La première est l'objet qui définit la fonction paramètres et variables locales, et la seconde est l'objet global. Dans une fonction imbriquée, la chaîne scope a trois objets ou plus. Il est important de comprendre comment cette chaîne des objets est créé. Quand une fonction est défini , il stocke la chaîne de portée puis dans effet. Lorsque cette fonction est invoquée , elle crée un nouvel objet pour stocker ses variables locales, et Ajoute ce nouvel objet à la chaîne scope stockée pour créer une nouvelle chaîne plus longue représente la portée de l'invocation de cette fonction. Cela devient plus intéressant pour fonctions imbriquées parce que chaque fois que la fonction externe est appelée, la fonction interne est définies à nouveau. Puisque la chaîne scope diffère sur chaque invocation de la fonction externe, la fonction interne sera subtilement différent chaque fois qu'il est défini-le code de l'intérieur fonction sera identique sur chaque invocation de la fonction externe, mais la chaîne de portée associée à ce code sera différent . Cette notion de chaîne de portée est essentielle pour comprendre les fermetures .

4
répondu Fanyo SILIADIN 2017-01-28 14:16:18
la source

Essayez ce curieux exemple. Dans l'exemple ci-dessous si un ont un numérique initialisé à 0, vous verriez 0 et 1. Sauf un est un objet javascript va passer f1 un pointeur d'une plutôt qu'une copie de celui-ci. Le résultat est que vous obtenez la même alerte les deux fois.

var a = new Date();
function f1(b)
{
    b.setDate(b.getDate()+1);
    alert(b.getDate());
}
f1(a);
alert(a.getDate());
3
répondu Mig82 2013-08-10 21:37:14
la source

ma compréhension est qu'il y a 3 portées: portée globale, disponible à l'échelle mondiale; portée locale, disponible pour une fonction entière indépendamment des blocs; et portée de bloc, disponible seulement pour le bloc, la déclaration, ou l'expression sur laquelle il a été utilisé. La portée globale et locale est indiquée par le mot-clé 'var', que ce soit à l'intérieur d'une fonction ou à l'extérieur, et la portée de bloc est indiquée par le mot-clé 'let'.

Pour ceux qui croient, il est seulement mondiale et locale, veuillez expliquez pourquoi Mozilla aurait une page entière décrivant les nuances de la portée de bloc dans JS.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let

3
répondu mrmaclean89 2017-09-17 01:35:07
la source

en JavaScript il y a deux types de champ d'application:

  • Locale
  • portée mondiale

la fonction ci-dessous a une variable de portée locale carName . Et cette variable n'est pas accessible depuis l'extérieur de la fonction.

function myFunction() {
    var carName = "Volvo";
    alert(carName);
    // code here can use carName
}

la classe ci-dessous a une variable de portée globale carName . Et cette variable est accessible de partout dans la classe.

class {

    var carName = " Volvo";

    // code here can use carName

    function myFunction() {
        alert(carName);
        // code here can use carName 
    }
}
2
répondu Abdur Rahman 2017-11-01 12:16:18
la source

Dans EcmaScript5, il y a principalement deux étendues, locale et de portée mondiale mais dans EcmaScript6 nous avons principalement trois domaines, de portée locale, de portée mondiale et un nouveau champ appelé bloc de portée .

exemple de champ d'application du bloc: -

for ( let i = 0; i < 10; i++)
{
 statement1...
statement2...// inside this scope we can access the value of i, if we want to access the value of i outside for loop it will give undefined.
}
1
répondu Vivek Mehta 2017-12-15 10:49:36
la source

ECMAScript 6 introduit les mots-clés let et const. Ces mots clés peuvent être utilisés à la place du mot-clé var. Contrairement au mot-clé var, les mots-clés let et const soutiennent la déclaration de portée locale à l'intérieur des énoncés de bloc.

var x = 10
let y = 10
const z = 10
{
  x = 20
  let y = 20
  const z = 20
  {
    x = 30
    // x is in the global scope because of the 'var' keyword
    let y = 30
    // y is in the local scope because of the 'let' keyword
    const z = 30
    // z is in the local scope because of the 'const' keyword
    console.log(x) // 30
    console.log(y) // 30
    console.log(z) // 30
  }
  console.log(x) // 30
  console.log(y) // 20
  console.log(z) // 20
}

console.log(x) // 30
console.log(y) // 10
console.log(z) // 10
1
répondu Dava E. 2018-02-09 18:37:12
la source

ES5 et plus:

les Variables en Javascript ont été initialement (pré ES6 ) la fonction lexique scoped. Le terme lexicalement scopé signifie que vous pouvez voir la portée des variables en "regardant" le code.

chaque variable déclarée avec le mot-clé var est scopée à la fonction. Toutefois, si d'autres fonctions sont déclarées à l'intérieur de cette fonction de ces fonctions auront accès à des variables de l'extérieur fonction. C'est ce qu'on appelle une chaîne de portée . Il fonctionne de la manière suivante:

  1. Lorsqu'une fonction cherche à résoudre une valeur variable, elle regarde d'abord sa propre portée. Il s'agit du corps de la fonction, c'est-à-dire tout ce qui se trouve entre crochets bouclés {} (à l'exception des variables à l'intérieur de autres fonctions qui relèvent de ce champ).
  2. S'il ne trouve pas la variable dans le le corps de la fonction il grimpera jusqu'à la chaîne et regarder la portée variable dans la fonction dans où la fonction a été définie . C'est ce qu'on entend par portée lexicale, on peut voir dans le code où cette fonction a été définie et donc déterminer la chaîne de portée en regardant simplement le code.

exemple:

// global scope
var foo = 'global';
var bar = 'global';
var foobar = 'global';

function outerFunc () {
 // outerFunc scope
 var foo = 'outerFunc';
 var foobar = 'outerFunc';
 innerFunc();
 
 function innerFunc(){
 // innerFunc scope
  var foo = 'innerFunc';
  console.log(foo);
  console.log(bar);
  console.log(foobar);
  }
}

outerFunc();

Ce qui arrive quand nous essayez d'enregistrer les variables foo , bar , et foobar sur la console est le suivant:

  1. nous essayons de connecter foo à la console, foo peut être trouvé à l'intérieur de la fonction innerFunc elle-même. Par conséquent, la valeur de foo est déterminée par la chaîne de caractères innerFunc .
  2. nous essayons de connecter bar à la console, bar ne peut pas être trouvé à l'intérieur de la fonction innerFunc elle-même. Par conséquent, nous devons monter la portée la chaîne . Nous regardons d'abord dans la fonction externe, dans lequel la fonction innerFunc a été défini. C'est la fonction outerFunc . Dans le champ d'application de outerFunc nous pouvons trouver la barre de variables, qui contient la chaîne de caractères "outerFunc".
  3. foobar ne se trouve pas dans innerFunc. . Par conséquent, nous devons grimper la chaîne de portée à la portée innerFunc. Il ne peut pas non plus être trouvé ici, nous montons un autre niveau à la portée globale (c'est-à-dire la portée extérieure). Nous trouvons ici la variable foobar qui contient la chaîne 'global'. S'il n'avait pas trouvé la variable après avoir escaladé la chaîne scope, le moteur JS lancerait une référence 1519310920".

ES6 (ES 2015) et plus:

Les mêmes concepts de lexicalement portée et scopechain s'appliquent toujours dans ES6 . Toutefois, une nouvelle façon de déclarer les variables a été introduite. Il y a les suivants:

  • let : crée un bloc de la variable scoped
  • const : crée une variable à portée de bloc qui doit être initialisée et ne peut pas être réattribuée

la plus grande différence entre var et let / const est que var est fonction scoped tandis que let / const sont Bloc scoped. Voici un exemple pour illustrer ceci:

let letVar = 'global';
var varVar = 'global';

function foo () {
  
  if (true) {
    // this variable declared with let is scoped to the if block, block scoped
    let letVar = 5;
    // this variable declared with let is scoped to the function block, function scoped
    var varVar = 10;
  }
  
  console.log(letVar);
  console.log(varVar);
}


foo();

dans l'exemple ci-dessus, letVar enregistre la valeur globale parce que les variables déclarées avec let sont définies par bloc. Ils cessent d'exister en dehors de leur bloc respectif, de sorte que la variable ne peut pas être accessible en dehors du bloc si.

0
répondu Willem van der Veen 2018-09-30 12:23:31
la source

il y a deux types de portées en JavaScript.

  1. portée globale : variable qui est annoncée dans la portée globale peut être utilisé n'importe où dans le programme très en douceur. Par exemple:

    var carName = " BMW";
    
    // code here can use carName
    
    function myFunction() {
         // code here can use carName 
    }
    
  2. portée fonctionnelle ou portée locale : la variable déclarée dans cette portée ne peut être utilisée que dans sa propre fonction. Par exemple:

    // code here can not use carName
    function myFunction() {
       var carName = "BMW";
       // code here can use carName
    }
    
-2
répondu A. Randhawa 2016-01-11 08:32:02
la source

Global: variable déclarée en dehors d'une fonction

Local: variable déclarée à l'intérieur d'une fonction, et ne peut être appelée que dans ce champ d'application""

-3
répondu poisonlocc 2015-01-03 22:35:52
la source

Autres questions sur javascript function scope variables var