Was ist eine kurze Einführung in das lexikalische Scoping?
Antworten
Zu viele Anzeigen?Lexikalisches Scoping: Variablen, die außerhalb einer Funktion deklariert werden, sind globale Variablen, die überall in einem JavaScript-Programm sichtbar sind. Variablen, die innerhalb einer Funktion deklariert sind, haben Funktionsumfang und sind nur für den Code sichtbar, der innerhalb dieser Funktion erscheint.
IBM definiert sie als:
Der Teil eines Programms oder einer Segmenteinheit, in dem eine Deklaration gilt. Ein in einer Routine deklarierter Bezeichner ist innerhalb dieser Routine und in allen verschachtelten Routinen bekannt. Deklariert eine verschachtelte Routine ein Element mit demselben Namen deklariert, ist das äußere Element in der verschachtelten Routine.
Beispiel 1:
function x() {
/*
Variable 'a' is only available to function 'x' and function 'y'.
In other words the area defined by 'x' is the lexical scope of
variable 'a'
*/
var a = "I am a";
function y() {
console.log( a )
}
y();
}
// outputs 'I am a'
x();
Beispiel 2:
function x() {
var a = "I am a";
function y() {
/*
If a nested routine declares an item with the same name,
the outer item is not available in the nested routine.
*/
var a = 'I am inner a';
console.log( a )
}
y();
}
// outputs 'I am inner a'
x();
Ich hoffe, das ist hilfreich. Hier ist mein Versuch einer etwas abstrakteren Definition:
Lexikalischer Anwendungsbereich : Der Zugriff oder die Reichweite, die etwas (z.B. eine Funktion oder Variable) zu anderen Elementen im Programm hat, bestimmt durch seine Position im Quellcode.
Übrigens baut meine Logik hier einfach auf den Definitionen von auf:
Lexikalisch : bezieht sich auf die Wörter oder das Vokabular einer Sprache (speziell das Wort, getrennt von seiner Grammatik oder seinem Aufbau) {in unserem Fall - eine Programmiersprache}.
Umfang (Substantiv): der Bereich der Operation {in unserem Fall ist der Bereich: das, worauf zugegriffen werden kann}.
Hinweis: Das Original von 1960 Definition von Lexical Scope
aus der ALGOL 60-Spezifikation ist viel prägnanter als mein obiger Versuch:
Lexikalische Reichweite: der Teil des Quellcodes, in dem eine Bindung eines Namens mit einer Entität gilt. fuente
Der lexikalische Bereich bezieht sich auf das Lexikon der Bezeichner (z. B. Variablen, Funktionen usw.), die von der aktuellen Position im Ausführungsstapel aus sichtbar sind.
- global execution context
- foo
- bar
- function1 execution context
- foo2
- bar2
- function2 execution context
- foo3
- bar3
foo
y bar
sind immer im Lexikon der verfügbaren Identifikatoren enthalten, da sie global sind.
Wenn function1
ausgeführt wird, hat es Zugriff auf ein Lexikon von foo2
, bar2
, foo
y bar
.
Wenn function2
ausgeführt wird, hat es Zugriff auf ein Lexikon von foo3
, bar3
, foo2
, bar2
, foo
y bar
.
Der Grund dafür, dass globale und/oder äußere Funktionen keinen Zugriff auf die Bezeichner einer inneren Funktion haben, liegt darin, dass die Ausführung dieser Funktion noch nicht stattgefunden hat und daher noch keine ihrer Bezeichner dem Speicher zugewiesen wurden. Darüber hinaus wird der innere Kontext nach seiner Ausführung vom Ausführungsstapel entfernt, was bedeutet, dass alle seine Bezeichner in den Müll geworfen wurden und nicht mehr verfügbar sind.
Aus diesem Grund kann ein verschachtelter Ausführungskontext IMMER auf den Ausführungskontext seines Vorgängers zugreifen und hat somit Zugang zu einem größeren Lexikon von Identifikatoren.
Siehe:
- https://tylermcginnis.com/ultimate-guide-to-execution-contexts-hoisting-scopes-and-closures-in-javascript/
- https://developer.mozilla.org/en-US/docs/Glossary/Identifier
Besonderen Dank an @robr3rd um die obige Definition zu vereinfachen.
Eine uralte Frage, aber hier ist meine Meinung dazu.
Lexikalisch (statischer) Bereich bezieht sich auf den Bereich einer Variablen in der Quellcode .
In einer Sprache wie JavaScript, wo Funktionen herumgereicht und an verschiedene Objekte angehängt und wieder angehängt werden können, könnte man meinen, dass der Geltungsbereich davon abhängt, wer die Funktion gerade aufruft, aber das tut er nicht. Das Ändern des Geltungsbereichs auf diese Weise wäre dynamischer Geltungsbereich, und JavaScript tut das nicht, außer vielleicht mit dem this
Objektreferenz.
Zur Veranschaulichung des Sachverhalts:
var a='apple';
function doit() {
var a='aardvark';
return function() {
alert(a);
}
}
var test=doit();
test();
In diesem Beispiel wird die Variable a
ist global definiert, wird aber in der doit()
Funktion. Diese Funktion gibt eine andere Funktion zurück, die sich, wie Sie sehen, auf die a
Variable außerhalb ihres eigenen Bereichs.
Wenn Sie dies ausführen, werden Sie feststellen, dass der verwendete Wert aardvark
, nicht apple
die zwar in den Anwendungsbereich der test()
Funktion, nicht im lexikalischen Bereich der ursprünglichen Funktion liegt. Das heißt, der verwendete Bereich ist der Bereich, wie er im Quellcode erscheint, und nicht der Bereich, in dem die Funktion tatsächlich verwendet wird.
Diese Tatsache kann unangenehme Folgen haben. Sie könnten zum Beispiel beschließen, dass es einfacher ist, Ihre Funktionen getrennt zu organisieren und sie dann zu gegebener Zeit zu verwenden, z. B. in einem Ereignis-Handler:
var a='apple',b='banana';
function init() {
var a='aardvark',b='bandicoot';
document.querySelector('button#a').onclick=function(event) {
alert(a);
}
document.querySelector('button#b').onclick=doB;
}
function doB(event) {
alert(b);
}
init();
<button id="a">A</button>
<button id="b">B</button>
In diesem Codebeispiel wird eines von beiden durchgeführt. Sie können sehen, dass aufgrund des lexikalischen Scopings die Schaltfläche A
verwendet die innere Variable, während die Schaltfläche B
nicht. Es kann sein, dass Sie mehr Funktionen verschachteln, als Ihnen lieb ist.
Übrigens werden Sie in beiden Beispielen auch feststellen, dass die inneren lexikalisch skalierten Variablen bestehen bleiben, auch wenn die enthaltende Funktion ihren Lauf genommen hat. Dies wird als Verschluss und bezieht sich auf den Zugriff einer verschachtelten Funktion auf äußere Variablen, auch wenn die äußere Funktion beendet ist. JavaScript muss intelligent genug sein, um festzustellen, ob diese Variablen nicht mehr benötigt werden, und wenn nicht, kann es sie zu Müll sammeln.
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.
50 Stimmen
Die Frage ist höflich, er sagt einfach, was er will. Es steht Ihnen frei, zu antworten. Hier besteht kein Bedarf an überempfindlicher Höflichkeit.
38 Stimmen
Ich finde Fragen wie diese großartig, weil sie Inhalte für SO schaffen. IMO, wen kümmert es, wenn die Frage keine Mühe macht... die Antworten werden großartigen Inhalt haben und das ist es, was in diesem Forum zählt.
10 Stimmen
Ich stimme mit @Jwan622 überein, dass eine Frage nicht langatmig sein muss, um eine gute Frage zu sein.