786 votes

Qu'est-ce que la portée lexicale ?

Quelle est une brève introduction au scoping lexical ?

100 votes

Dans le podcast 58, Joel encourage les questions de ce genre car il souhaite que SO devienne LE lieu où l'on trouve des réponses, même si elles ont déjà été données ailleurs. Cette question est valable, même si on pourrait la formuler de manière un peu plus polie.

0 votes

Et puis surtout fr.wikipedia.org/wiki/Scope_(programmation) qui contient un bel exemple (Pascal/Delphi) de scopes imbriqués dans des procédures imbriquées.

7 votes

@rahul Je comprends que c'est une vieille question. Mais je suis sûr que même en 2009, SO s'attendait à ce que les demandeurs mettent en quelques efforts de base pour le résoudre. En l'état actuel des choses, il ne montre pas tout effort du tout. C'est peut-être pour cela qu'il a été descendu par beaucoup ?

37voto

Simple As Could Be Points 3906

J'aime les réponses complètes, sans distinction de langue, de gens comme @Arak. Puisque cette question a été étiquetée JavaScript Cependant, j'aimerais ajouter quelques remarques très spécifiques à ce langage.

En JavaScript, nos choix pour le cadrage sont les suivants :

  • tel quel (pas de réglage de la portée)
  • lexical var _this = this; function callback(){ console.log(_this); }
  • lié callback.bind(this)

Il est intéressant de noter, je pense, que JavaScript n'a pas vraiment de portée dynamique . .bind permet de régler le this mot-clé, et c'est proche, mais pas techniquement le même.

Voici un exemple illustrant les deux approches. Vous faites cela à chaque fois que vous prenez une décision sur la façon d'étendre les callbacks, donc cela s'applique aux promesses, aux gestionnaires d'événements, et plus encore.

Lexical

Voici ce que vous pourriez appeler Lexical Scoping de callbacks en JavaScript :

var downloadManager = {
  initialize: function() {
    var _this = this; // Set up `_this` for lexical access
    $('.downloadLink').on('click', function () {
      _this.startDownload();
    });
  },
  startDownload: function(){
    this.thinking = true;
    // Request the file from the server and bind more callbacks for when it returns success or failure
  }
  //...
};

Lié

Une autre façon de procéder est d'utiliser Function.prototype.bind :

var downloadManager = {
  initialize: function() {
    $('.downloadLink').on('click', function () {
      this.startDownload();
    }.bind(this)); // Create a function object bound to `this`
  }
//...

Ces méthodes sont, pour autant que je sache, équivalentes sur le plan comportemental.

2 votes

Utilisation de bind n'affecte pas la portée.

31voto

Shivendra Gupta Points 378

Portée lexicale signifie que dans un groupe de fonctions imbriquées, les fonctions internes ont accès aux variables et aux autres ressources de leur portée parent. .

Cela signifie que les fonctions de l'enfant sont liées lexicalement au contexte d'exécution de leurs parents.

La portée lexicale est parfois aussi appelée champ statique .

function grandfather() {
    var name = 'Hammad';
    // 'likes' is not accessible here
    function parent() {
        // 'name' is accessible here
        // 'likes' is not accessible here
        function child() {
            // Innermost level of the scope chain
            // 'name' is also accessible here
            var likes = 'Coding';
        }
    }
}

La chose que vous remarquerez à propos de la portée lexicale est qu'elle fonctionne en avant, ce qui signifie que le nom peut être accédé par les contextes d'exécution de ses enfants.

Mais il ne fonctionne pas à rebours vers ses parents, ce qui signifie que la variable likes ne peut pas être consulté par ses parents.

Cela nous indique également que les variables ayant le même nom dans différents contextes d'exécution ont la priorité de haut en bas de la pile d'exécution.

Une variable, dont le nom est similaire à celui d'une autre variable, dans la fonction la plus interne (contexte le plus haut de la pile d'exécution) aura une plus grande priorité.

Fuente .

30voto

Praveen Kishor Points 16

Une portée lexicale en JavaScript signifie qu'une variable définie en dehors d'une fonction peut être accessible dans une autre fonction définie après la déclaration de la variable. Mais l'inverse n'est pas vrai ; les variables définies à l'intérieur d'une fonction ne seront pas accessibles en dehors de cette fonction.

Ce concept est fortement utilisé dans les fermetures en JavaScript.

Disons que nous avons le code suivant.

var x = 2;
var add = function() {
    var y = 1;
    return x + y;
};

Maintenant, lorsque vous appelez add() --> cela va imprimer 3.

Ainsi, la fonction add() accède à la variable globale x qui est défini avant la fonction méthode add. Ceci est dû au scoping lexical en JavaScript.

1 votes

Considérons que l'extrait de code concerne un langage à portée dynamique. Si le add() qui serait appelée immédiatement après l'extrait de code donné, elle imprimerait également 3. Le scoping lexical ne signifie pas simplement qu'une fonction peut accéder aux variables globales en dehors du contexte local. L'exemple de code n'aide donc pas vraiment à montrer ce que signifie le lexical scoping. Montrer la portée lexicale dans le code nécessite vraiment un contre-exemple ou au moins une explication des autres interprétations possibles du code.

20voto

Sky Points 3391

En langage simple, la portée lexicale est une variable définie en dehors de votre portée ou la portée supérieure est automatiquement disponible à l'intérieur de votre portée, ce qui signifie que vous n'avez pas besoin de l'y passer.

Ejemplo:

let str="JavaScript";

const myFun = () => {
    console.log(str);
}

myFun();

// Sortie : JavaScript

2 votes

La réponse la plus courte et la meilleure pour moi avec un exemple. On aurait pu ajouter que les fonctions flèches de ES6' résolvent le problème avec bind . Avec eux, le bind n'est plus nécessaire. Pour plus d'informations sur ce changement, consultez stackoverflow.com/a/34361380/11127383

13voto

Stan Points 39

Portée lexicale : Les variables déclarées en dehors d'une fonction sont des variables globales et sont visibles partout dans un programme JavaScript. Les variables déclarées à l'intérieur d'une fonction ont une portée de fonction et ne sont visibles que pour le code qui apparaît dans cette fonction.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X