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 ?

3voto

Sean Points 436

J'espère que cela vous aidera, voici ma tentative de définition un peu plus abstraite :

Portée lexicale : L'accès ou la portée que quelque chose (par exemple une fonction ou une variable) a à d'autres éléments du programme, tel que déterminé par sa position dans le code source.

En passant, ma logique ici se base simplement sur les définitions de :

Lexical : relatif aux mots ou au vocabulaire d'une langue (spécifiquement le mot en tant que séparé de sa grammaire ou de sa construction) {dans notre cas - un langage de programmation}.

Portée (nom) : la gamme d'opérations {dans notre cas, la gamme est : ce à quoi on peut accéder}.

Note, l'original de 1960 définition de Lexical Scope de la spécification ALGOL 60 est bien plus concise que ma tentative ci-dessus :

Portée lexicale : la partie du code source dans laquelle s'applique la liaison d'un nom avec une entité. fuente

2voto

er0 Points 704

Voici un angle différent de cette question que nous pouvons obtenir en prenant un peu de recul et en examinant le rôle du cadrage dans le cadre plus large de l'interprétation (exécution d'un programme). En d'autres termes, imaginez que vous construisiez un interpréteur (ou un compilateur) pour un langage et que vous soyez responsable du calcul de la sortie, étant donné un programme et une entrée pour celui-ci.

L'interprétation implique de tenir compte de trois éléments :

  1. État - à savoir, les variables et les emplacements mémoire référencés sur le tas et la pile.

  2. Les opérations sur cet état - à savoir, chaque ligne de code dans votre programme

  3. El environnement dans laquelle une opération fonctionne - à savoir, la projection de état sur une opération.

Un interprète commence à la première ligne de code d'un programme, calcule son environnement, exécute la ligne dans cet environnement et capture son effet sur l'état du programme. Il suit ensuite le flux de contrôle du programme pour exécuter la ligne de code suivante, et répète le processus jusqu'à la fin du programme.

La manière dont vous calculez l'environnement pour une opération quelconque passe par un ensemble formel de règles définies par le langage de programmation. Le terme "binding" est fréquemment utilisé pour décrire la mise en correspondance de l'état global du programme avec une valeur de l'environnement. Notez que par "état général", nous n'entendons pas l'état global, mais plutôt la somme totale de chaque définition atteignable, à tout moment de l'exécution).

Il s'agit du cadre dans lequel le problème de cadrage est défini. Passons maintenant à la partie suivante, à savoir quelles sont nos options.

  • En tant qu'implémenteur de l'interpréteur, vous pourriez vous simplifier la tâche en rendant l'environnement aussi proche que possible de l'état du programme. En conséquence, l'environnement d'une ligne de code serait simplement défini par l'environnement de la ligne de code précédente avec les effets de cette opération appliqués à celle-ci, que la ligne précédente soit une affectation, un appel de fonction, le retour d'une fonction ou une structure de contrôle telle qu'une boucle while.

C'est l'essentiel de cadrage dynamique L'environnement dans lequel s'exécute un code est lié à l'état du programme tel que défini par son contexte d'exécution.

  • O Vous pouvez donc imaginer qu'un programmeur utilise votre langage et lui simplifier la tâche en lui permettant de garder la trace des valeurs que peut prendre une variable. Il y a beaucoup trop de chemins et trop de complexité dans le raisonnement sur le résultat de la totalité des exécutions passées. Portée lexicale aide à faire cela en restreignant l'environnement actuel à la portion de l'état défini dans le bloc, la fonction ou toute autre unité de portée actuelle, et son parent (c'est-à-dire le bloc entourant l'horloge actuelle, ou la fonction qui a appelé la présente fonction).

En d'autres termes, avec portée lexicale l'environnement que tout code voit est lié à l'état associé à une portée définie explicitement dans le langage, comme un bloc ou une fonction.

0voto

Tal Galili Points 4627

Voici une explication dans le cas de R.

0voto

Daniel Danielecki Points 118

Ce sujet est fortement lié à l'intégration bind et introduite dans l'ECMAScript 6 Fonctions des flèches . C'était vraiment ennuyeux, car pour chaque nouvelle méthode de "classe" (fonction en fait) que nous voulions utiliser, nous devions bind ceci afin d'avoir accès à la portée.

Par défaut, JavaScript ne définit pas son champ d'application en matière de this sur les fonctions (il ne définit pas le contexte en this ). Par défaut, vous devez indiquer explicitement quel contexte que vous voulez avoir.

El fonctions de la flèche obtient automatiquement ce qu'on appelle portée lexicale (avoir accès à la définition de la variable dans son bloc contenant). Lorsque vous utilisez fonctions de la flèche il lie automatiquement this à l'endroit où la fonction flèche a été définie en premier lieu, et l'élément contexte de cette fonctions de la flèche est le bloc qui le contient.

Voyez comment cela fonctionne en pratique sur les exemples les plus simples ci-dessous.

Avant les fonctions de la flèche (pas de portée lexicale par défaut) :

const programming = {
  language: "JavaScript",
  getLanguage: function() {
    return this.language;
  }
}

const globalScope = programming.getLanguage;
console.log(globalScope()); // Output: undefined

const localScope = programming.getLanguage.bind(programming);
console.log(localScope()); // Output: "JavaScript"

Avec fonctions de flèche (portée lexicale par défaut) :

const programming = {
  language: "JavaScript",
  getLanguage: function() {
    return this.language;
  }
}

const arrowFunction = () => {
    console.log(programming.getLanguage());
}

arrowFunction(); // Output: "JavaScript"

-1voto

Karl Morrison Points 774

J'apprends normalement par l'exemple, et voici un petit quelque chose :

const lives = 0;

function catCircus () {
    this.lives = 1;
    const lives = 2;

    const cat1 = {
        lives: 5,
        jumps: () => {
            console.log(this.lives);
        }
    };
    cat1.jumps(); // 1
    console.log(cat1); // { lives: 5, jumps: [Function: jumps] }

    const cat2 = {
        lives: 5,
        jumps: () => {
            console.log(lives);
        }
    };
    cat2.jumps(); // 2
    console.log(cat2); // { lives: 5, jumps: [Function: jumps] }

    const cat3 = {
        lives: 5,
        jumps: () => {
            const lives = 3;
            console.log(lives);
        }
    };
    cat3.jumps(); // 3
    console.log(cat3); // { lives: 5, jumps: [Function: jumps] }

    const cat4 = {
        lives: 5,
        jumps: function () {
            console.log(lives);
        }
    };
    cat4.jumps(); // 2
    console.log(cat4); // { lives: 5, jumps: [Function: jumps] }

    const cat5 = {
        lives: 5,
        jumps: function () {
            var lives = 4;
            console.log(lives);
        }
    };
    cat5.jumps(); // 4
    console.log(cat5); // { lives: 5, jumps: [Function: jumps] }

    const cat6 = {
        lives: 5,
        jumps: function () {
            console.log(this.lives);
        }
    };
    cat6.jumps(); // 5
    console.log(cat6); // { lives: 5, jumps: [Function: jumps] }

    const cat7 = {
        lives: 5,
        jumps: function thrownOutOfWindow () {
            console.log(this.lives);
        }
    };
    cat7.jumps(); // 5
    console.log(cat7); // { lives: 5, jumps: [Function: thrownOutOfWindow] }
}

catCircus();

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