web-dev-qa-db-fra.com

Chaîne de portée en Javascript

J'ai lu la chaîne de portée en Javascript, mais cela n'avait aucun sens pour moi, quelqu'un pourrait-il me dire ce qu'est la chaîne de portée et comment cela fonctionne avec un graphique ou quelque chose que même un idiot peut comprendre. Je l'ai googlé mais je n'ai pas trouvé quelque chose de compréhensible :(

53
Tarik

Pour comprendre la chaîne de portée, vous devez savoir comment fonctionnent les fermetures.

Une fermeture est formée lorsque vous imbriquez des fonctions, les fonctions internes peuvent faire référence aux variables présentes dans leurs fonctions englobantes externes même après que leurs fonctions parentes ont déjà été exécutées.

JavaScript résout les identifiants dans un contexte particulier en parcourant la chaîne de portée, en passant du local au global.

Considérez cet exemple avec trois fonctions imbriquées:

var currentScope = 0; // global scope
(function () {
  var currentScope = 1, one = 'scope1';
  alert(currentScope);
  (function () {
    var currentScope = 2, two = 'scope2';
    alert(currentScope);
    (function () {
      var currentScope = 3, three = 'scope3';
      alert(currentScope);
      alert(one + two + three); // climb up the scope chain to get one and two
    }());
  }());
}());

Lectures recommandées:

57
CMS

Tout appel de fonction dans ECMAScript (langage de base sur lequel JS est basé) produit un contexte d'exécution distinct, qui s'exécute individuellement les uns des autres. À l'intérieur de chaque contexte d'exécution, this fait référence à l'objet en question, par défaut à tout ce à quoi la fonction est attachée.

function foo() {
    alert(this===window)
}

Alerterait vrai, car la fenêtre est l'objet qui possède la méthode 'foo'. Toutes les variables définies dans une fonction sont accessibles via la chaîne de portée unique de cette fonction, l'environnement.

function world() {
    var name = 'global';
    alert(name)
}

alerterait évidemment "global".

function world() {
    var name = 'global';
    (function() {
        var name = 'country';
        alert(name)
    })();
    alert(name)
}

Dans le dernier exemple, lorsque la première alerte est invoquée, Javascript détermine que dans la chaîne d'étendue de la fonction interne que l'identifiant name est défini, il n'a donc pas à rechercher la chaîne d'étendue pour l'attraper. .

Dans la deuxième invocation d'alerte, name est également défini dans le même contexte et alerte "global";

function world() {
    var name = 'global';
    (function() { alert(name) })();
}

Dans cet exemple, l'identifiant name n'est pas défini dans le même contexte et doit donc remonter la chaîne de portée jusqu'à la fonction externe où le nom est défini, et il alerte global.

Référence:

17
meder omuraliev

Je sais que c'est un ancien article mais il est toujours utile pour les développeurs. Je voulais le faire de manière légèrement différente car il serait plus convivial pour les débutants de comprendre le chaînage de la portée. Voici ma version modifiée du code:

var currentScope = 0; // global scope
function a () {
   var currentScope = 1, one = 'scope1';
   alert(currentScope);

  function b () {
      var currentScope = 2, two = 'scope2';
      alert(currentScope);

      function c () {
         var currentScope = 3, three = 'scope3';
         alert(currentScope);
  alert(one + two + three); // climb up the scope chain to get one and two
     }
     c();
  }
  b();
}
a();
5
JVM

Il s'agit de fermeture. Vous pouvez utiliser des variables externes à la portée dans la portée interne:

function get_inner_scope () {
    var outer = 'Outer variable value';
    return function () {
        alert(outer);
    }
}
f = get_inner_scope();
f(); // alerts Outer variable value

Plus d'informations détaillées avec d'autres exemples par le premier lien de Google: http://blogs.msdn.com/jscript/archive/2007/07/26/scope-chain-of-jscript-functions.aspx

5
Anatoliy

Chaîne de portée en Javascript expliquée en termes simples

Alex est un gars heureux, Un beau jour, marchant sur la route avec son salaire mensuel en main est agressé.

Plus tard, il se rend compte que demain est le dernier jour pour payer les frais de scolarité de ses filles de 1000 $.
Il court chez lui, trouve ses économies de 400 $, s'inquiète du reste (600 $). La pensée immédiate qui clignote, est d'en emprunter à son père Mathew.
Mathew, le pauvre charpentier, dépourvu de tout argent, vend son bracelet hérité pour 300 $ et le prête à son fils Alex.
Alex ayant une bonne réputation dans la société, obtient immédiatement les 300 $ restants d'une banque locale et paie les frais de scolarité de sa fille à temps.

Revenir à la chaîne Scope en Javascript:
Fonction Alex-A en javascript
Mathew-La fonction immédiate, Alex est imbriqué.
Parents de Mathews - La fonction immédiate de Mathew est imbriquée.
Variables Bank-Global.

function Bank() {
    loan=300;
    Mathew();

    function Mathew() {
        mathew=300;
        Alex();

        function Alex() {
            savings:400;
            alert('I need some money');
        }

    }

}

Bank();

La chaîne de portée d'Alex à ce stade ressemble à: [économies: 400] + [mathew: 300] + [prêt: 300];

3
Sai Chandra

Résumé:

La chaîne de portée est utilisée pour résoudre la valeur des noms de variables en javascript. Sans chaîne d'étendue, le moteur Javascript ne saurait pas quelle valeur choisir pour un certain nom de variable s'il y en a plusieurs définis à différentes étendues. La chaîne de portée en javascript est définie lexicalement , ce qui signifie que nous pouvons voir quelle sera la chaîne de portée en regardant le code.

En haut de la chaîne d'étendue se trouve l'étendue globale, qui est l'objet window dans le navigateur (global dans NodeJS). Outre la portée globale, les fonctions ont leur propre portée de variables. La chaîne de portée peut être déterminée en regardant où les fonctions sont définies.

Lors de la résolution d'une variable, les fonctions internes examinent d'abord leur propre portée. Si la variable ne peut pas être trouvée dans sa propre portée, elle grimpera dans la chaîne de portée et recherchera le nom de la variable dans l'environnement où la fonction a été définie. Cela ressemble à ceci:

Scope chain javascript

Ainsi, dans notre exemple d'image lorsque innerFoo utilise la variable bar, il essaie d'abord de la trouver dans la portée de innerFoo (code dans le corps de la fonction). Puis, quand il ne le trouve pas ici, il monte la chaîne de portée à foo. Dans foo, il n'y a pas non plus de variable nommée bar. Par conséquent, il grimpera la chaîne de portée et regardera maintenant dans la portée mondiale. Dans la portée globale se trouve une variable nommée bar avec une valeur de 10 à laquelle bar sera résolu.

Exemple:

let foo = 1;
let bar = 1;


function test (bar) {
   
   return function innerTestFunc () {
      let foo = 10;
      
      console.log(foo, bar);
    }
  
}

const innerTestFunc1 = test(5);
const innerTestFunc2 = test(20);


innerTestFunc1();  // logs 10, 5

innerTestFunc2();  // logs 10, 20

Dans l'exemple ci-dessus, nous avons une fonction qui renvoie une fonction. Nous stockons d'abord cette fonction dans les variables innerTestFunc1 et innerTestFunc2. Cela crée une fermeture qui est essentiellement un instantané de la chaîne de portée de l'environnement extérieur.

Ensuite, lorsque les fonctions sont exécutées, la fonction requiert une valeur pour les variables foo et bar. La valeur de foo peut être résolue au niveau de innerTestFunc et vaut 10 pour les deux. 10 se trouve déjà dans innerFoo, donc pas besoin de grimper la chaîne de portée pour foo.

Dans le cas de la variable bar, la fonction ne la trouve pas dans la innerFoo. Par conséquent, il grimpera la chaîne de portée. Il rencontre d'abord la variable bar dans la fonction test, donc il résoudra la valeur de bar en quelle que soit la valeur de la fonction de test (5, 20 dans notre exemple) .

1