Was ist eine kurze Einführung in das lexikalische Scoping?
Was ist eine kurze Einführung in das lexikalische Scoping?
Antworten:
Ich verstehe sie anhand von Beispielen. :) :)
Zunächst der lexikalische Bereich (auch als statischer Bereich bezeichnet ) in C-ähnlicher Syntax:
void fun()
{
int x = 5;
void fun2()
{
printf("%d", x);
}
}
Jede innere Ebene kann auf ihre äußeren Ebenen zugreifen.
Es gibt einen anderen Weg, der als dynamischer Bereich bezeichnet wird und von der ersten Implementierung von Lisp verwendet wird , wiederum in einer C-ähnlichen Syntax:
void fun()
{
printf("%d", x);
}
void dummy1()
{
int x = 5;
fun();
}
void dummy2()
{
int x = 10;
fun();
}
Hier fun
kann entweder auf x
in dummy1
oder dummy2
oder auf eine x
beliebige Funktion zugegriffen werden, die fun
mit x
deklariert aufgerufen wird.
dummy1();
druckt 5,
dummy2();
druckt 10.
Der erste wird als statisch bezeichnet, da er zur Kompilierungszeit abgeleitet werden kann, und der zweite wird als dynamisch bezeichnet, da der äußere Bereich dynamisch ist und vom Kettenaufruf der Funktionen abhängt.
Ich finde statisches Scoping für das Auge einfacher. Die meisten Sprachen gingen diesen Weg schließlich, sogar Lisp (kann beides, oder?). Dynamisches Scoping ist wie das Übergeben von Referenzen aller Variablen an die aufgerufene Funktion.
Als Beispiel dafür, warum der Compiler den äußeren dynamischen Bereich einer Funktion nicht ableiten kann, betrachten wir unser letztes Beispiel. Wenn wir so etwas schreiben:
if(/* some condition */)
dummy1();
else
dummy2();
Die Aufrufkette hängt von einer Laufzeitbedingung ab. Wenn es wahr ist, sieht die Anrufkette wie folgt aus:
dummy1 --> fun()
Wenn die Bedingung falsch ist:
dummy2 --> fun()
Der äußere Bereich von ist fun
in beiden Fällen der Anrufer plus der Anrufer des Anrufers und so weiter .
Nur um zu erwähnen, dass die C-Sprache weder verschachtelte Funktionen noch dynamisches Scoping zulässt.
JavaScript
. Daher denke ich, dass dies nicht als akzeptierte Antwort markiert werden sollte. Lexikalischer Umfang speziell in JS ist anders
for
ist das typische Problem innerhalb einer Schleife. Der lexikalische Bereich für JavaScript befindet sich nur auf Funktionsebene, sofern nicht ES6 let
oder const
verwendet wird.
Versuchen wir die kürzestmögliche Definition:
Lexikalisches Scoping definiert, wie Variablennamen in verschachtelten Funktionen aufgelöst werden: Innere Funktionen enthalten den Umfang der übergeordneten Funktionen, auch wenn die übergeordnete Funktion zurückgegeben wurde .
Das ist alles was dazu gehört!
var scope = "I am global";
function whatismyscope(){
var scope = "I am just a local";
function func() {return scope;}
return func;
}
whatismyscope()()
Der obige Code gibt "Ich bin nur ein Einheimischer" zurück. Es wird nicht "Ich bin ein Global" zurückgegeben. Weil die Funktion func () zählt, wo ursprünglich definiert wurde, was unter den Funktionsumfang whatismyscope fällt.
Es wird sich nicht darum kümmern, was auch immer es genannt wird (der globale Bereich / sogar innerhalb einer anderen Funktion), deshalb wird der globale Bereichswert, den ich global bin, nicht gedruckt.
Dies wird als lexikalisches Scoping bezeichnet, bei dem " Funktionen mithilfe der Gültigkeitsbereichskette ausgeführt werden, die zum Zeitpunkt der Definition gültig war " - gemäß JavaScript Definition Guide.
Lexikalischer Bereich ist ein sehr sehr leistungsfähiges Konzept.
Hoffe das hilft..:)
Lexikalisches (statisches AKA) Scoping bezieht sich auf die Bestimmung des Gültigkeitsbereichs einer Variablen ausschließlich anhand ihrer Position innerhalb des Textcode-Korpus. Eine Variable bezieht sich immer auf ihre Umgebung der obersten Ebene. Es ist gut, es in Bezug auf den dynamischen Umfang zu verstehen .
Der Bereich definiert den Bereich, in dem Funktionen, Variablen und dergleichen verfügbar sind. Die Verfügbarkeit einer Variablen wird beispielsweise im Kontext definiert, beispielsweise in der Funktion, Datei oder dem Objekt, in dem sie definiert sind. Wir nennen diese lokalen Variablen normalerweise.
Der lexikalische Teil bedeutet, dass Sie den Umfang aus dem Lesen des Quellcodes ableiten können.
Der lexikalische Bereich wird auch als statischer Bereich bezeichnet.
Der dynamische Bereich definiert globale Variablen, die nach der Definition von überall aufgerufen oder referenziert werden können. Manchmal werden sie als globale Variablen bezeichnet, obwohl globale Variablen in den meisten Programmiersprachen lexikalisch sind. Dies bedeutet, dass aus dem Lesen des Codes abgeleitet werden kann, dass die Variable in diesem Kontext verfügbar ist. Möglicherweise muss man einer Verwendungs- oder Includes-Klausel folgen, um die Instanziierung oder Definition zu finden, aber der Code / Compiler kennt die Variable an dieser Stelle.
Im Gegensatz dazu suchen Sie beim dynamischen Scoping zuerst in der lokalen Funktion, dann in der Funktion, die die lokale Funktion aufgerufen hat, dann in der Funktion, die diese Funktion aufgerufen hat, und so weiter im Aufrufstapel. "Dynamisch" bezieht sich auf eine Änderung, da der Aufrufstapel bei jedem Aufruf einer bestimmten Funktion unterschiedlich sein kann und die Funktion daher je nach Aufruf möglicherweise unterschiedliche Variablen trifft. (siehe hier )
Ein interessantes Beispiel für den dynamischen Bereich finden Sie hier .
Weitere Details finden Sie hier und hier .
Einige Beispiele in Delphi / Object Pascal
Delphi hat einen lexikalischen Geltungsbereich.
unit Main;
uses aUnit; // makes available all variables in interface section of aUnit
interface
var aGlobal: string; // global in the scope of all units that use Main;
type
TmyClass = class
strict private aPrivateVar: Integer; // only known by objects of this class type
// lexical: within class definition,
// reserved word private
public aPublicVar: double; // known to everyboday that has access to a
// object of this class type
end;
implementation
var aLocalGlobal: string; // known to all functions following
// the definition in this unit
end.
Das Delphi, das dem dynamischen Bereich am nächsten kommt, ist das Funktionspaar RegisterClass () / GetClass (). Zur Verwendung siehe hier .
Angenommen, die Zeit, zu der RegisterClass ([TmyClass]) aufgerufen wird, um eine bestimmte Klasse zu registrieren, kann nicht durch Lesen des Codes vorhergesagt werden (dies wird in einer vom Benutzer aufgerufenen Button-Click-Methode aufgerufen). Der Code, der GetClass ('TmyClass') aufruft, wird abgerufen ein Ergebnis oder nicht. Der Aufruf von RegisterClass () muss mit GetClass () nicht im lexikalischen Bereich der Einheit liegen.
Eine weitere Möglichkeit für den dynamischen Bereich sind anonyme Methoden (Closures) in Delphi 2009, da sie die Variablen ihrer aufrufenden Funktion kennen. Es folgt dem aufrufenden Pfad von dort nicht rekursiv und ist daher nicht vollständig dynamisch.
Ich liebe die voll funktionsfähigen, sprachunabhängigen Antworten von Leuten wie @Arak. Da diese Frage mit JavaScript getaggt wurde , möchte ich einige Notizen einfügen, die für diese Sprache sehr spezifisch sind.
In JavaScript haben wir folgende Möglichkeiten für das Scoping:
var _this = this; function callback(){ console.log(_this); }
callback.bind(this)
Ich denke, es ist erwähnenswert, dass JavaScript nicht wirklich über ein dynamisches Scoping verfügt . .bind
Passt das this
Schlüsselwort an, und das ist nah, aber technisch nicht dasselbe.
Hier ist ein Beispiel, das beide Ansätze demonstriert. Sie tun dies jedes Mal, wenn Sie eine Entscheidung darüber treffen, wie Rückrufe behandelt werden sollen. Dies gilt also für Versprechen, Ereignishandler und mehr.
Folgendes können Sie Lexical Scoping
als Rückrufe in JavaScript bezeichnen:
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
}
//...
};
Eine andere Möglichkeit zum Umfang besteht darin, Folgendes zu verwenden Function.prototype.bind
:
var downloadManager = {
initialize: function() {
$('.downloadLink').on('click', function () {
this.startDownload();
}.bind(this)); // Create a function object bound to `this`
}
//...
Diese Methoden sind meines Wissens verhaltensmäßig gleichwertig.
bind
hat keinen Einfluss auf den Umfang.
Lexikalisches Scoping: Variablen, die außerhalb einer Funktion deklariert wurden, sind globale Variablen und überall in einem JavaScript-Programm sichtbar. Innerhalb einer Funktion deklarierte Variablen haben einen Funktionsumfang und sind nur für Code sichtbar, der in dieser Funktion angezeigt wird.
IBM definiert es 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. Wenn eine verschachtelte Routine ein Element mit demselben Namen deklariert, ist das äußere Element in der verschachtelten Routine nicht verfügbar.
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();
Lexikalischer Bereich bedeutet, dass in einer verschachtelten Gruppe von Funktionen die inneren Funktionen Zugriff auf die Variablen und andere Ressourcen ihres übergeordneten Bereichs haben . Dies bedeutet, dass die untergeordneten Funktionen lexikalisch an den Ausführungskontext ihrer Eltern gebunden sind. Der lexikalische Bereich wird manchmal auch als statischer Bereich bezeichnet .
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';
}
}
}
Was Sie am lexikalischen Bereich bemerken werden, ist, dass es vorwärts funktioniert, was bedeutet, dass auf den Namen von den Ausführungskontexten seiner Kinder zugegriffen werden kann. Es funktioniert jedoch nicht rückwärts für die Eltern, was bedeutet, dass die Eltern likes
nicht auf die Variable zugreifen können.
Dies zeigt uns auch, dass Variablen mit demselben Namen in verschiedenen Ausführungskontexten von oben nach unten im Ausführungsstapel Vorrang haben. Eine Variable mit einem ähnlichen Namen wie eine andere Variable in der innersten Funktion (oberster Kontext des Ausführungsstapels) hat eine höhere Priorität.
Beachten Sie, dass dies von hier übernommen wird .
In einfacher Sprache ist der lexikalische Bereich eine Variable, die außerhalb Ihres Bereichs definiert ist, oder der obere Bereich ist automatisch innerhalb Ihres Bereichs verfügbar, was bedeutet, dass Sie ihn dort nicht übergeben müssen.
Beispiel:
let str="JavaScript";
const myFun = () => {
console.log(str);
}
myFun();
// Ausgabe: JavaScript
bind
. Bei ihnen ist das bind
nicht mehr erforderlich. Weitere Informationen zu dieser Änderung finden Sie unter stackoverflow.com/a/34361380/11127383
Es fehlt ein wichtiger Teil der Konversation über das lexikalische und dynamische Scoping : eine einfache Erklärung der Lebensdauer der Scoping-Variablen - oder wann auf die Variable zugegriffen werden kann.
Dynamisches Scoping entspricht nur sehr lose dem "globalen" Scoping, wie wir es traditionell betrachten (der Grund, warum ich den Vergleich zwischen beiden anspreche, ist, dass es bereits erwähnt wurde - und ich mag die Erklärung des verlinkten Artikels nicht besonders ); Es ist wahrscheinlich am besten, wenn wir keinen Vergleich zwischen global und dynamisch anstellen - obwohl laut dem verlinkten Artikel "... [es] als Ersatz für Variablen mit globalem Gültigkeitsbereich nützlich sein soll".
Was ist also im Klartext der wichtige Unterschied zwischen den beiden Scoping-Mechanismen?
Das lexikalische Scoping wurde in den obigen Antworten sehr gut definiert: Variablen mit lexikalischem Scoping 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, hat das dynamische Scoping nicht viel Aufmerksamkeit erhalten, und die Aufmerksamkeit, die es erhalten hat, bedeutet, dass es wahrscheinlich etwas mehr braucht (das ist keine Kritik an anderen Antworten, sondern eher ein "oh, Diese Antwort ließ uns wünschen, es gäbe ein bisschen mehr "). Also, hier ist ein bisschen mehr:
Dynamisches Scoping bedeutet, dass eine Variable während der Lebensdauer des Funktionsaufrufs oder während der Ausführung der Funktion für das größere Programm zugänglich ist. Wirklich, Wikipedia macht einen guten Job mit der Erklärung des Unterschieds zwischen den beiden. Um dies nicht zu verschleiern, finden Sie hier den Text, der das dynamische Scoping beschreibt:
... [I] In einem dynamischen Bereich (oder einem dynamischen Bereich) ist der Bereich eines Variablennamens eine bestimmte Funktion, und sein Bereich ist der Zeitraum, in dem die Funktion ausgeführt wird: Während die Funktion ausgeführt wird, existiert der Variablenname und ist an seine Variable gebunden, aber nachdem die Funktion zurückgegeben wurde, existiert der Variablenname nicht.
Lexikalischer Bereich bedeutet, dass eine Funktion Variablen in dem Kontext sucht, in dem sie definiert wurde, und nicht in dem Bereich, der sie unmittelbar umgibt.
Sehen Sie sich an, wie der lexikalische Bereich in Lisp funktioniert wenn Sie weitere Details wünschen. Die ausgewählte Antwort von Kyle Cronin in Dynamische und Lexikalische Variablen in Common Lisp ist viel klarer als die Antworten hier.
Zufälligerweise habe ich dies nur in einer Lisp-Klasse erfahren, und es gilt zufällig auch in JavaScript.
Ich habe diesen Code in der Chrome-Konsole ausgeführt.
// JavaScript Equivalent Lisp
var x = 5; //(setf x 5)
console.debug(x); //(print x)
function print_x(){ //(defun print-x ()
console.debug(x); // (print x)
} //)
(function(){ //(let
var x = 10; // ((x 10))
console.debug(x); // (print x)
print_x(); // (print-x)
})(); //)
Ausgabe:
5
10
5
Ein lexikalischer Bereich in JavaScript bedeutet, dass auf eine außerhalb einer Funktion definierte Variable innerhalb einer anderen nach der Variablendeklaration definierten Funktion zugegriffen werden kann. Das Gegenteil ist jedoch nicht der Fall. Auf die innerhalb einer Funktion definierten Variablen kann außerhalb dieser Funktion nicht zugegriffen werden.
Dieses Konzept wird häufig in Abschlüssen in JavaScript verwendet.
Nehmen wir an, wir haben den folgenden Code.
var x = 2;
var add = function() {
var y = 1;
return x + y;
};
Wenn Sie nun add () -> aufrufen, wird 3 gedruckt.
Die Funktion add () greift also auf die globale Variable zu, x
die vor der Methodenfunktion add definiert wurde. Dies wird aufgrund des lexikalischen Bereichs in JavaScript aufgerufen.
add()
Funktion unmittelbar nach dem angegebenen Codeausschnitt aufgerufen wird, wird auch 3 ausgegeben. Lexikalisches Scoping bedeutet nicht einfach, dass eine Funktion auf globale Variablen außerhalb des lokalen Kontexts zugreifen kann. Der Beispielcode hilft also nicht wirklich zu zeigen, was lexikalisches Scoping bedeutet. Das Anzeigen des lexikalischen Bereichs im Code erfordert wirklich ein Gegenbeispiel oder zumindest eine Erklärung anderer möglicher Interpretationen des Codes.
Der lexikalische Bereich bezieht sich auf das Lexikon von Bezeichnern (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
und bar
befinden sich immer im Lexikon der verfügbaren Bezeichner, da diese global sind.
Wenn function1
ausgeführt wird, hat es Zugriff auf ein Lexikon foo2
, bar2
, foo
, und bar
.
Wenn function2
ausgeführt wird, hat es Zugriff auf ein Lexikon foo3
, bar3
, foo2
, bar2
, foo
, und bar
.
Der Grund, warum globale und / oder äußere Funktionen keinen Zugriff auf Bezeichner für innere Funktionen haben, liegt darin, dass die Ausführung dieser Funktion noch nicht erfolgt ist und daher keiner ihrer Bezeichner dem Speicher zugewiesen wurde. Sobald dieser innere Kontext ausgeführt wird, wird er aus dem Ausführungsstapel entfernt, was bedeutet, dass alle seine Bezeichner durch Müll gesammelt wurden und nicht mehr verfügbar sind.
Aus diesem Grund kann ein verschachtelter Ausführungskontext IMMER auf den Ausführungskontext seiner Vorfahren zugreifen und hat daher Zugriff auf ein größeres Lexikon von Bezeichnern.
Sehen:
Besonderer Dank geht an @ robr3rd für die Hilfe bei der Vereinfachung der obigen Definition.
Hier ist ein anderer Blickwinkel auf diese Frage, den wir erhalten können, wenn wir einen Schritt zurücktreten und die Rolle des Scoping im größeren Interpretationsrahmen (Ausführen eines Programms) betrachten. Mit anderen Worten, stellen Sie sich vor, Sie hätten einen Interpreter (oder Compiler) für eine Sprache erstellt und wären für die Berechnung der Ausgabe verantwortlich, wenn Sie ein Programm und einige Eingaben dafür gegeben hätten.
Bei der Interpretation müssen drei Dinge im Auge behalten werden:
Status - nämlich Variablen und referenzierte Speicherorte auf dem Heap und Stack.
Operationen in diesem Zustand - nämlich jede Codezeile in Ihrem Programm
Die Umgebung, in der eine bestimmte Operation ausgeführt wird - nämlich die Projektion des Zustands auf eine Operation.
Ein Interpreter beginnt in der ersten Codezeile eines Programms, berechnet seine Umgebung, führt die Zeile in dieser Umgebung aus und erfasst deren Auswirkungen auf den Programmstatus. Es folgt dann dem Kontrollfluss des Programms, um die nächste Codezeile auszuführen, und wiederholt den Vorgang, bis das Programm endet.
Die Art und Weise, wie Sie die Umgebung für eine Operation berechnen, erfolgt über ein formales Regelwerk, das von der Programmiersprache definiert wird. Der Begriff "Bindung" wird häufig verwendet, um die Zuordnung des Gesamtzustands des Programms zu einem Wert in der Umgebung zu beschreiben. Beachten Sie, dass mit "Gesamtzustand" nicht der globale Zustand gemeint ist, sondern die Gesamtsumme jeder erreichbaren Definition zu jedem Zeitpunkt der Ausführung.
Dies ist der Rahmen, in dem das Scoping-Problem definiert wird. Nun zum nächsten Teil unserer Optionen.
Dies ist der Kern des dynamischen Scoping , bei dem die Umgebung, in der Code ausgeführt wird, an den Status des Programms gebunden ist, der durch seinen Ausführungskontext definiert ist.
Mit anderen Worten, mit lexikalischem Bereich ist die Umgebung, die jeder Code sieht, an den Status gebunden, der einem Bereich zugeordnet ist, der explizit in der Sprache definiert ist, z. B. ein Block oder eine Funktion.
Alte Frage, aber hier ist meine Einstellung dazu.
Der lexikalische (statische) Bereich bezieht sich auf den Bereich einer Variablen im Quellcode .
In einer Sprache wie JavaScript, in der Funktionen weitergegeben und an verschiedene Objekte angehängt und wieder angehängt werden können, hängt dieser Bereich möglicherweise davon ab, wer die Funktion gerade aufruft, dies ist jedoch nicht der Fall. Das Ändern des Bereichs auf diese Weise wäre ein dynamischer Bereich, und JavaScript tut dies nicht, außer möglicherweise mit demthis
Objektreferenz.
Um den Punkt zu veranschaulichen:
var a='apple';
function doit() {
var a='aardvark';
return function() {
alert(a);
}
}
var test=doit();
test();
Im Beispiel ist die Variable a
global definiert, jedoch in der doit()
Funktion schattiert . Diese Funktion gibt eine andere Funktion zurück, die, wie Sie sehen, auf der basierta
Variablen außerhalb ihres eigenen Bereichs .
Wenn Sie dies ausführen, werden Sie feststellen, dass der verwendete Wert aardvark
nicht apple
welcher ist, obwohl er im Bereich von liegttest()
Funktion, ist nicht in dem lexikalischen Umfang der ursprünglichen Funktion. Das heißt, der verwendete Bereich ist der Bereich, wie er im Quellcode angezeigt wird, nicht der Bereich, in dem die Funktion tatsächlich verwendet wird.
Diese Tatsache kann ärgerliche Folgen haben. Sie können beispielsweise entscheiden, dass es einfacher ist, Ihre Funktionen separat zu organisieren und sie dann zu gegebener Zeit zu verwenden, z. B. in einem Ereignishandler:
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>
Dieses Codebeispiel führt jeweils eines aus. Sie können sehen, dass die Schaltfläche aufgrund des lexikalischen Gültigkeitsbereichs A
die innere Variable while-Schaltfläche verwendetB
dies nicht tut. Möglicherweise erhalten Sie mehr Verschachtelungsfunktionen, als Sie gerne hätten.
Übrigens werden Sie in beiden Beispielen auch feststellen, dass die Variablen mit dem inneren lexikalischen Gültigkeitsbereich bestehen bleiben, obwohl die enthaltende Funktionsfunktion ihren Lauf genommen hat. Dies wird als Abschluss bezeichnet und bezieht sich auf den Zugriff einer verschachtelten Funktion auf äußere Variablen, selbst wenn die äußere Funktion beendet wurde. JavaScript muss intelligent genug sein, um festzustellen, ob diese Variablen nicht mehr benötigt werden, und wenn nicht, kann sie durch Müll gesammelt werden.
Normalerweise lerne ich anhand eines Beispiels und hier ist etwas:
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();
Dieses Thema ist mit der eingebauten in engen Zusammenhang mit bind
Funktion und eingeführt in ECMAScript 6 Pfeil Funktionen . Es war wirklich ärgerlich, denn für jede neue "Klasse" -Methode (Funktion tatsächlich), die wir verwenden wollten, mussten wir bind
dies tun , um Zugriff auf den Bereich zu erhalten.
JavaScript standardmäßig nicht ihren Anwendungsbereich this
auf Funktionen (so dass er nicht den Kontext auf this
). Standardmäßig müssen Sie explizit angeben, welchen Kontext Sie haben möchten.
Die Pfeilfunktionen erhalten automatisch einen sogenannten lexikalischen Bereich (Zugriff auf die Variablendefinition in ihrem enthaltenen Block). Beim Benutzen Pfeilfunktionen wird automatisch an this
die Stelle gebunden, an der die Pfeilfunktion ursprünglich definiert wurde, und der Kontext dieser Pfeilfunktionen ist der enthaltende Block.
Sehen Sie anhand der einfachsten Beispiele unten, wie es in der Praxis funktioniert.
Vor Pfeilfunktionen (standardmäßig kein lexikalischer Bereich):
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"