849 Stimmen

Was ist lexikalischer Geltungsbereich?

Was ist eine kurze Einführung in das lexikalische Scoping?

109 Stimmen

In Podcast 58 ermutigt Joel zu Fragen wie diesen, da er möchte, dass SO DER Ort für Antworten wird, auch wenn sie bereits an anderer Stelle beantwortet wurden. Dies ist eine berechtigte Frage, auch wenn man sie etwas höflicher formulieren könnte.

0 Stimmen

Und dann speziell de.wikipedia.org/wiki/Scope_(Programmierung) die ein schönes (Pascal/Delphi) Beispiel für verschachtelte Bereiche in verschachtelten Prozeduren enthält.

18 Stimmen

Es ist möglich, dass der Fragesteller nicht fließend Englisch spricht (oder sprach), als er diese Frage schrieb.

4voto

Thomas Punkte 5373

Es gibt einen wichtigen Teil des Gesprächs über lexikalisch y dynamisches Scoping was noch fehlt: eine einfache Erklärung der Lebensdauer der skalierten Variablen - oder wenn kann auf die Variable zugegriffen werden.

Dynamisches Scoping entspricht nur sehr grob dem "globalen" Scoping, wie wir es uns traditionell vorstellen (der Grund, warum ich den Vergleich zwischen den beiden anführe, ist, dass er bereits erwähnt - und ich mag nicht besonders die verlinkt Erklärung des Artikels); es ist wahrscheinlich am besten, wenn wir den Vergleich zwischen global und dynamisch nicht machen - obwohl angeblich, laut dem verlinkten Artikel, "...[es] als Ersatz für global skalierte Variablen nützlich ist."

Worin besteht also der wichtige Unterschied zwischen den beiden Scoping-Mechanismen?

Die lexikalische Skalierung wurde in den obigen Antworten sehr gut definiert: lexikalisch skalierte Variablen sind auf der lokalen Ebene der Funktion, in der sie definiert wurden, verfügbar - oder zugänglich -.

Da es jedoch nicht im Mittelpunkt des OP steht, wurde dem dynamischen Scoping nicht viel Aufmerksamkeit gewidmet, und die Aufmerksamkeit, die es erhalten hat, bedeutet, dass es wahrscheinlich ein bisschen mehr braucht (das ist keine Kritik an anderen Antworten, sondern eher ein "Oh, diese Antwort hat uns dazu gebracht, dass wir uns ein bisschen mehr wünschen"). Also, hier ist ein bisschen mehr:

Dynamisches Scoping bedeutet, dass eine Variable während der Dauer des Funktionsaufrufs - oder während der Ausführung der Funktion - für das gesamte Programm zugänglich ist. Wirklich, Wikipedia macht eine gute Arbeit mit dem Erklärung des Unterschieds zwischen den beiden. Um die Sache nicht zu verkomplizieren, hier der Text, der das dynamische Scoping beschreibt:

...[I]m dynamischen Scoping (oder dynamischen Geltungsbereich), wenn der Geltungsbereich eines Variablennamens ein eine bestimmte Funktion ist, dann ist sein Geltungsbereich der Zeitraum, in dem die Funktion ausgeführt wird: Während die Funktion läuft, existiert der Variablenname Name und ist an seine Variable gebunden, aber nachdem die Funktion zurückkehrt, existiert der Variablenname nicht mehr.

2voto

er0 Punkte 1611

Hier ist ein anderer Blickwinkel auf diese Frage, den wir erhalten können, wenn wir einen Schritt zurückgehen und die Rolle des Scoping im größeren Rahmen der Interpretation (Ausführung eines Programms) betrachten. Mit anderen Worten: Stellen Sie sich vor, Sie bauen einen Interpreter (oder Compiler) für eine Sprache und sind für die Berechnung der Ausgabe verantwortlich, wenn Sie ein Programm und eine Eingabe haben.

Beim Dolmetschen müssen drei Dinge beachtet werden:

  1. Zustand - d.h. Variablen und referenzierte Speicherplätze auf dem Heap und Stack.

  2. Operationen an diesem Zustand - nämlich jede Codezeile in Ihrem Programm

  3. Le site Umwelt in dem eine bestimmte Betrieb läuft - nämlich die Projektion von état auf eine Operation.

Ein Interpreter beginnt mit der ersten Codezeile in einem Programm, berechnet seine Umgebung, führt die Zeile in dieser Umgebung aus und erfasst ihre Auswirkungen auf den Programmzustand. Anschließend folgt er dem Kontrollfluss des Programms, um die nächste Codezeile auszuführen, und wiederholt diesen Vorgang bis zum Ende des Programms.

Die Art und Weise, wie Sie die Umgebung für eine beliebige Operation berechnen, ist durch einen formalen Satz von Regeln, die durch die Programmiersprache definiert sind. Der Begriff "Bindung" wird häufig verwendet, um die Abbildung des Gesamtzustands des Programms auf einen Wert in der Umgebung zu beschreiben. Beachten Sie, dass wir mit "Gesamtzustand" nicht den globalen Zustand meinen, sondern die Summe aller erreichbaren Definitionen zu jedem Zeitpunkt der Ausführung.)

Dies ist der Rahmen, in dem das Scoping-Problem definiert wird. Nun zum nächsten Teil, den Optionen, die wir haben.

  • Als Implementierer des Interpreters könnten Sie Ihre Aufgabe vereinfachen, indem Sie die Umgebung so nah wie möglich an den Zustand des Programms heranführen. Dementsprechend würde die Umgebung einer Codezeile einfach durch die Umgebung der vorangegangenen Codezeile mit den Auswirkungen dieser Operation definiert, unabhängig davon, ob die vorangegangene Zeile eine Zuweisung, ein Funktionsaufruf, die Rückkehr aus einer Funktion oder eine Kontrollstruktur wie eine while-Schleife war.

Dies ist das Wesentliche an dynamisches Scoping Die Umgebung, in der ein Code läuft, ist an den Zustand des Programms gebunden, der durch seinen Ausführungskontext definiert ist.

  • Oder können Sie sich einen Programmierer vorstellen, der Ihre Sprache verwendet, und ihm die Aufgabe erleichtern, die Werte, die eine Variable annehmen kann, im Auge zu behalten. Es gibt viel zu viele Pfade und zu viel Komplexität, wenn es darum geht, über das Ergebnis der Gesamtheit der vergangenen Ausführung nachzudenken. Lexikalisches Scoping hilft dabei, indem es die aktuelle Umgebung auf den Teil des Zustands definiert in den aktuellen Block, die aktuelle Funktion oder eine andere Einheit des Geltungsbereichs sowie deren übergeordnete Einheit (d. h. der Block, der die aktuelle Uhr umschließt, oder die Funktion, die die aktuelle Funktion aufgerufen hat).

Mit anderen Worten, mit lexikalische Reichweite die Umgebung, die jeder Code sieht, ist an einen Zustand gebunden, der mit einem explizit in der Sprache definierten Bereich, wie einem Block oder einer Funktion, verbunden ist.

0voto

Daniel Danielecki Punkte 5658

Dieses Thema steht in engem Zusammenhang mit dem eingebauten bind Funktion und wurde in ECMAScript 6 eingeführt Pfeil-Funktionen . Es war wirklich ärgerlich, weil wir für jede neue "Klassen"-Methode (eigentlich eine Funktion), die wir verwenden wollten, Folgendes tun mussten bind um Zugang zum Geltungsbereich zu erhalten.

JavaScript setzt standardmäßig nicht den Geltungsbereich von this auf Funktionen (es setzt nicht die Kontext auf this ). Standardmäßig müssen Sie explizit angeben, welche Kontext die Sie haben möchten.

Le site Pfeilfunktionen erhält automatisch sogenannte lexikalische Reichweite (Zugriff auf die Variablendefinition in dem sie enthaltenden Block). Bei der Verwendung von Pfeilfunktionen es bindet automatisch this zu der Stelle, an der die Pfeilfunktion ursprünglich definiert wurde, und die Kontext dieser Pfeilfunktionen ist sein enthaltender Block.

Wie das in der Praxis funktioniert, sehen Sie unten an den einfachsten Beispielen.

Vor Pfeil-Funktionen (standardmäßig kein lexikalischer Geltungsbereich):

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"

Mit Pfeilfunktionen (standardmäßig lexikalischer Bereich):

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

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

arrowFunction(); // Output: "JavaScript"

0voto

Youjun Hu Punkte 585

Lexikalisches Scoping bedeutet, dass Funktionen freie Variablen aus dem Bereich auflösen, in dem sie definiert wurden, nicht aus dem Bereich, in dem sie aufgerufen werden.

0 Stimmen

Was etwas freisetzt, hat nichts mit dem lexikalischen Umfang zu tun und ist ohnehin nur in Nicht-GC-Sprachen von Bedeutung.

-1voto

basickarl Punkte 31184

Normalerweise lerne ich durch Beispiele, und hier ist ein kleines Beispiel:

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();

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X