Was ist der Umfang der Variablen in Javascript? Haben sie innerhalb und außerhalb einer Funktion den gleichen Gültigkeitsbereich? Oder spielt es überhaupt eine Rolle? Wo werden die Variablen gespeichert, wenn sie global definiert sind?
Ich denke, das Beste, was ich tun kann, ist, Ihnen eine Reihe von Beispielen zu geben, die Sie studieren können. Javascript-Programmierer werden praktisch danach eingestuft, wie gut sie den Umfang verstehen. Es kann manchmal ziemlich kontraintuitiv sein.
Eine Variable mit globalem Gültigkeitsbereich
// global scope
var a = 1;
function one() {
alert(a); // alerts '1'
}
Lokaler Geltungsbereich
// global scope
var a = 1;
function two(a) { // passing (a) makes it local scope
alert(a); // alerts the given argument, not the global value of '1'
}
// local scope again
function three() {
var a = 3;
alert(a); // alerts '3'
}
Intermediate : In JavaScript gibt es keinen Blockbereich (ES5; ES6 führt let
) ein. )
ein.
var a = 1;
function four() {
if (true) {
var a = 4;
}
alert(a); // alerts '4', not the global value of '1'
}
b.
var a = 1;
function one() {
if (true) {
let a = 4;
}
alert(a); // alerts '1' because the 'let' keyword uses block scoping
}
Intermediate : Objekteigenschaften
var a = 1;
function Five() {
this.a = 5;
}
alert(new Five().a); // alerts '5'
Advanced : Closure
var a = 1;
var six = (function() {
var a = 6;
return function() {
// JavaScript "closure" means I have access to 'a' in here,
// because it is defined in the function in which I was defined.
alert(a); // alerts '6'
};
})();
Erweitert : Prototypbasierte Bereichsauflösung
var a = 1;
function seven() {
this.a = 7;
}
// [object].prototype.property loses to
// [object].property in the lookup chain. For example...
// Won't get reached, because 'a' is set in the constructor above.
seven.prototype.a = -1;
// Will get reached, even though 'b' is NOT set in the constructor.
seven.prototype.b = 8;
alert(new seven().a); // alerts '7'
alert(new seven().b); // alerts '8'
Global + Lokal : Ein besonders komplexer Fall
var x = 5;
(function () {
console.log(x);
var x = 10;
console.log(x);
})();
Dadurch werden undefined
und 10
anstelle von 5
und 10
ausgegeben, da JavaScript Variablendeklarationen (nicht Initialisierungen) immer an den oberen Rand des Gültigkeitsbereichs verschiebt. Der Code entspricht dabei:
var x = 5;
(function () {
var x;
console.log(x);
x = 10;
console.log(x);
})();
Catch-Klausel-Variable
var e = 5;
console.log(e);
try {
throw 6;
} catch (e) {
console.log(e);
}
console.log(e);
Dies gibt 5
, 6
, 5
aus. In der catch-Klausel spiegelt e
globale und lokale Variablen. Dieser spezielle Gültigkeitsbereich gilt jedoch nur für die erfasste Variable. Wenn Sie var f;
in die catch-Klausel schreiben, ist dies genauso, als hätten Sie es vor oder nach dem try-catch-Block definiert.
Javascript verwendet Gültigkeitsbereichsketten, um den Gültigkeitsbereich für eine bestimmte Funktion festzulegen. In der Regel gibt es einen globalen Bereich, und jede definierte Funktion verfügt über einen eigenen verschachtelten Bereich. Jede innerhalb einer anderen Funktion definierte Funktion hat einen lokalen Gültigkeitsbereich, der mit der äußeren Funktion verknüpft ist. Es ist immer die Position in der Quelle, die den Umfang definiert.
Ein Element in der Bereichskette ist im Grunde eine Map mit einem Zeiger auf den übergeordneten Bereich.
Beim Auflösen einer Variablen beginnt Javascript im innersten Bereich und sucht nach außen.
Global deklarierte Variablen haben einen globalen Gültigkeitsbereich. Variablen, die innerhalb einer Funktion deklariert wurden, gelten für diese Funktion und spiegeln globale Variablen mit demselben Namen wider.
(Ich bin sicher, dass es viele Feinheiten gibt, auf die echte JavaScript-Programmierer in anderen Antworten hinweisen können. Insbesondere bin ich auf diese Seite gestoßen, was genau this
zu jeder Zeit bedeutet. Hoffentlich dieser einleitende Link reicht jedoch aus, um Ihnen den Einstieg zu erleichtern.)
Traditionell gibt es in JavaScript nur zwei Arten von Gültigkeitsbereichen:
Ich werde darauf nicht näher eingehen, da es bereits viele andere Antworten gibt, die den Unterschied erklären.
Die neuesten JavaScript-Spezifikationen erlauben jetzt auch einen dritten Bereich:
Traditionell erstellen Sie Ihre Variablen folgendermaßen:
var myVariable = "Some text";
Blockbereichsvariablen werden folgendermaßen erstellt:
let myVariable = "Some text";
Beachten Sie den folgenden Code, um den Unterschied zwischen Funktionsumfang und Blockumfang zu verstehen:
// i IS NOT known here
// j IS NOT known here
// k IS known here, but undefined
// l IS NOT known here
function loop(arr) {
// i IS known here, but undefined
// j IS NOT known here
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
for( var i = 0; i < arr.length; i++ ) {
// i IS known here, and has a value
// j IS NOT known here
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
};
// i IS known here, and has a value
// j IS NOT known here
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
for( let j = 0; j < arr.length; j++ ) {
// i IS known here, and has a value
// j IS known here, and has a value
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
};
// i IS known here, and has a value
// j IS NOT known here
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
}
loop([1,2,3,4]);
for( var k = 0; k < arr.length; k++ ) {
// i IS NOT known here
// j IS NOT known here
// k IS known here, and has a value
// l IS NOT known here
};
for( let l = 0; l < arr.length; l++ ) {
// i IS NOT known here
// j IS NOT known here
// k IS known here, and has a value
// l IS known here, and has a value
};
loop([1,2,3,4]);
// i IS NOT known here
// j IS NOT known here
// k IS known here, and has a value
// l IS NOT known here
Hier sehen wir, dass unsere Variable j
nur in der ersten for-Schleife bekannt ist, nicht jedoch davor und danach. Unsere Variable i
ist jedoch in der gesamten Funktion bekannt.
Bedenken Sie auch, dass blockspezifische Variablen nicht bekannt sind, bevor sie deklariert werden, da sie nicht angehoben werden. Es ist auch nicht gestattet, dieselbe blockspezifische Variable innerhalb desselben Blocks erneut zu deklarieren. Dadurch sind Variablen mit Block-Gültigkeitsbereich weniger fehleranfällig als Variablen mit globalem oder funktionalem Gültigkeitsbereich, die angehoben werden und bei Mehrfachdeklarationen keine Fehler verursachen.
Ob es heute sicher ist oder nicht, hängt von Ihrer Umgebung ab:
Wenn Sie serverseitigen JavaScript-Code schreiben ( Node.js ), können Sie die Anweisung let
sicher verwenden.
Wenn Sie clientseitigen JavaScript-Code schreiben und einen browserbasierten Transpiler verwenden (wie Traceur oder babel-standalone ), Sie können die let
-Anweisung ohne Bedenken verwenden, Ihr Code ist jedoch in Bezug auf die Leistung wahrscheinlich alles andere als optimal.
Wenn Sie clientseitigen JavaScript-Code schreiben und einen Node -basierten Transpiler verwenden (wie das traceur Shell-Skript oder Babel ), können Sie die let
-Anweisung sicher verwenden. Und da Ihr Browser nur den transpilierten Code kennt, sollten die Leistungseinbußen begrenzt sein.
Wenn Sie clientseitigen JavaScript-Code schreiben und keinen Transpiler verwenden, müssen Sie die Browserunterstützung in Betracht ziehen.
Dies sind einige Browser, die let
überhaupt nicht unterstützen:
Eine aktuelle Übersicht darüber, welche Browser zum Zeitpunkt des Lesens dieser Antwort die Anweisung let
unterstützen, finden Sie auf der Seite this Can I Use
.
(*) Variablen mit globalem und funktionalem Gültigkeitsbereich können initialisiert und verwendet werden, bevor sie deklariert werden, da JavaScript-Variablen hoisted . Dies bedeutet, dass Erklärungen immer ganz oben im Geltungsbereich stehen.
(**) Blockbereichsvariablen werden nicht gehisst
Hier ist ein Beispiel:
<script>
var globalVariable = 7; //==window.globalVariable
function aGlobal( param ) { //==window.aGlobal();
//param is only accessible in this function
var scopedToFunction = {
//can't be accessed outside of this function
nested : 3 //accessible by: scopedToFunction.nested
};
anotherGlobal = {
//global because there's no `var`
};
}
</script>
Sie möchten die Schließungen untersuchen und wissen, wie Sie daraus private Mitglieder erstellen.
Der Schlüssel, wie ich es verstehe, ist, dass Javascript das Scoping auf Funktionsebene gegenüber dem allgemeineren C-Block-Scoping hat.
In "Javascript 1.7" (Mozillas Erweiterung auf Javascript) kann man Block-Scope-Variablen auch mit let
statement deklarieren:
var a = 4;
let (a = 3) {
alert(a); // 3
}
alert(a); // 4
Die Idee, JavaScript zu verwenden, als es ursprünglich von Brendan Eich entworfen wurde, stammt aus der HyperCard Skriptsprache HyperTalk .
In dieser Sprache wurden die Anzeigen ähnlich einem Stapel von Karteikarten gemacht. Es gab eine Masterkarte, die als Hintergrund bezeichnet wurde. Es war transparent und kann als unterste Karte angesehen werden. Alle Inhalte auf dieser Basiskarte wurden mit darauf platzierten Karten geteilt. Jede oben platzierte Karte hatte ihren eigenen Inhalt, der Vorrang vor der vorherigen Karte hatte, aber auf Wunsch immer noch Zugriff auf die vorherigen Karten.
Genau so ist das JavaScript-Scoping-System aufgebaut. Es hat nur verschiedene Namen. Die Karten in JavaScript werden als Ausführungskontexte) bezeichnetECMA. Jeder dieser Kontexte enthält drei Hauptteile. Eine variable Umgebung, eine lexikalische Umgebung und eine solche Bindung. Zurück zur Kartenreferenz: Die lexikalische Umgebung enthält den gesamten Inhalt früherer Karten, die sich weiter unten im Stapel befinden. Der aktuelle Kontext befindet sich oben im Stapel, und alle dort deklarierten Inhalte werden in der variablen Umgebung gespeichert. Die variable Umgebung hat Vorrang bei der Benennung von Kollisionen.
Diese Bindung verweist auf das enthaltende Objekt. Manchmal ändern sich Bereiche oder Ausführungskontexte, ohne dass sich das enthaltende Objekt ändert, z. B. in einer deklarierten Funktion, in der das enthaltende Objekt window
oder eine Konstruktorfunktion sein kann.
Diese Ausführungskontexte werden jedes Mal erstellt, wenn die Steuerung übertragen wird. Die Steuerung wird übertragen, wenn die Ausführung von Code beginnt, und dies erfolgt hauptsächlich durch die Ausführung von Funktionen.
Das ist also die technische Erklärung. In der Praxis ist es wichtig, dies in JavaScript zu berücksichtigen
Wenn Sie dies auf eines der vorherigen Beispiele (5. "Closure") auf dieser Seite anwenden, ist es möglich, den Stapel von Ausführungskontexten zu verfolgen. In diesem Beispiel befinden sich drei Kontexte im Stapel. Sie werden durch den äußeren Kontext, den Kontext in der sofort aufgerufenen Funktion, die von var six aufgerufen wird, und den Kontext in der zurückgegebenen Funktion innerhalb der sofort aufgerufenen Funktion von var six definiert.
i ) Der äußere Kontext. Es hat eine variable Umgebung von a = 1
ii ) Im IIFE-Kontext hat es eine lexikalische Umgebung von a = 1, aber eine variable Umgebung von a = 6, die im Stapel Vorrang hat
iii ) Der zurückgegebene Funktionskontext weist eine lexikalische Umgebung von a = 6 auf. Dies ist der Wert, auf den in der Warnung verwiesen wird, wenn sie aufgerufen wird.
1) Es gibt einen globalen Bereich, einen Funktionsbereich sowie den Bereich with und catch. Generell gibt es keinen Gültigkeitsbereich auf Blockebene für Variablen - die Anweisungen with und catch fügen ihren Blöcken Namen hinzu.
2) Bereiche werden von Funktionen bis zum globalen Bereich verschachtelt.
3) Eigenschaften werden durch Durchlaufen der Prototypenkette gelöst. Die with-Anweisung bringt Objekteigenschaftsnamen in den durch den with-Block definierten lexikalischen Bereich.
BEARBEITEN: ECMAAScript 6 (Harmony) ist so spezifiziert, dass es let unterstützt, und ich weiß, dass chrome ein "Harmony" -Flag zulässt, also unterstützt es es vielleicht.
Let wäre eine Unterstützung für das Scoping auf Blockebene, aber Sie müssen das Schlüsselwort verwenden, um dies zu erreichen.
BEARBEITEN: Basierend auf Benjamins Hinweis auf die with- und catch-Anweisungen in den Kommentaren habe ich den Beitrag bearbeitet und weitere hinzugefügt. Sowohl die with-Anweisung als auch die catch-Anweisung führen Variablen in ihre jeweiligen Blöcke ein, und das ist ein Blockbereich. Diese Variablen sind an die Eigenschaften der übergebenen Objekte angepasst.
//chrome (v8)
var a = { 'test1':'test1val' }
test1 // error not defined
with (a) { var test1 = 'replaced' }
test1 // undefined
a // a.test1 = 'replaced'
EDIT: Klärendes Beispiel:
test1 hat einen Gültigkeitsbereich für den with-Block, ist jedoch mit einem Alias für a.test1 versehen. 'Var test1' erstellt eine neue Variable test1 im oberen lexikalischen Kontext (Funktion oder global), es sei denn, es ist eine Eigenschaft von a - was es ist.
Huch! Seien Sie vorsichtig mit 'with' - so wie var ein Noop ist, wenn die Variable bereits in der Funktion definiert ist, ist es auch ein Noop in Bezug auf die aus dem Objekt importierten Namen! Ein kleiner Hinweis auf den bereits definierten Namen würde dies viel sicherer machen. Ich persönlich werde nie damit umgehen.
Ich habe festgestellt, dass viele Leute, die noch kein JavaScript haben, Probleme damit haben, zu verstehen, dass Vererbung standardmäßig in der Sprache verfügbar ist und der Funktionsumfang der einzige Bereich ist. Ich lieferte eine Erweiterung für einen Kosmetiker namens JSPretty, den ich Ende letzten Jahres geschrieben hatte. Das Feature colors funktioniert im Code im Bereich und ordnet allen in diesem Bereich deklarierten Variablen immer eine Farbe zu. Das Schließen wird visuell demonstriert, wenn eine Variable mit einer Farbe aus einem Bereich in einem anderen Bereich verwendet wird.
Probieren Sie die Funktion unter:
Sehen Sie sich eine Demo an unter:
Den Code finden Sie unter:
Derzeit bietet die Funktion Unterstützung für eine Tiefe von 16 verschachtelten Funktionen, färbt jedoch derzeit keine globalen Variablen.
JavaScript hat nur zwei Arten von Gültigkeitsbereichen:
var
deklarierte Variable hat einen Funktionsumfang.Jedes Mal, wenn eine Funktion aufgerufen wird, wird ein variables Bereichsobjekt erstellt (und in die Bereichskette aufgenommen), gefolgt von Variablen in JavaScript.
a = "global";
function outer(){
b = "local";
console.log(a+b); //"globallocal"
}
outer();
Umfangskette ->
a
und outer
befinden sich in der Scope-Kette auf der obersten Ebene.variable scope object
(und in der Bereichskette enthalten) mit der Variablen b
darin aufgerufen hat.Wenn nun eine Variable a
benötigt wird, wird zuerst nach dem nächstgelegenen Variablenbereich gesucht, und wenn die Variable nicht vorhanden ist, wird zum nächsten Objekt der Variablenbereichskette gewechselt. In diesem Fall handelt es sich um die Fensterebene.
Nur um die anderen Antworten zu ergänzen, ist scope eine Nachschlageliste aller deklarierten Bezeichner (Variablen) und erzwingt strenge Regeln, wie auf diese zugegriffen werden kann, um aktuell Code auszuführen. Diese Suche kann zum Zuweisen zu der Variablen dienen, die eine LHS-Referenz (linke Seite) ist, oder zum Abrufen ihres Werts, der eine RHS-Referenz (rechte Seite) ist. Diese Suchvorgänge werden von der JavaScript-Engine intern ausgeführt, wenn der Code kompiliert und ausgeführt wird.
Aus dieser Perspektive denke ich, dass ein Bild helfen würde, das ich im Scopes and Closures-eBook von Kyle Simpson gefunden habe:
Zitat aus seinem E-Book:
Das Gebäude repräsentiert den Regelsatz für den verschachtelten Bereich unseres Programms. Die erste Etage des Gebäudes repräsentiert Ihren aktuell ausgeführten Bereich, wo immer Sie sich befinden. Die oberste Ebene des Gebäudes ist die globale Reichweite. Sie lösen LHS- und RHS-Verweise auf, indem Sie in der aktuellen Etage nachsehen. Wenn Sie sie nicht finden, fahren Sie mit dem Aufzug in die nächste Etage und suchen dort die nächste usw. Sobald Sie in der obersten Etage (dem globalen Bereich) angekommen sind, finden Sie entweder das, wonach Sie suchen, oder Sie finden es nicht. Aber du musst trotzdem aufhören.
Erwähnenswert ist Folgendes: "Die Scope-Suche stoppt, sobald die erste Übereinstimmung gefunden wurde".
Diese Idee von "Bereichsebenen" erklärt, warum "dies" mit einem neu erstellten Bereich geändert werden kann, wenn er in einer verschachtelten Funktion nachgeschlagen wird. Hier ist ein Link, der in all diese Details geht, Alles, was Sie über Javascript wissen wollten
Globale Variablen sind genau wie globale Sterne (Jackie Chan, Nelson Mandela). Sie können von jedem Teil Ihrer Anwendung aus darauf zugreifen (Wert abrufen oder festlegen). Globale Funktionen sind wie globale Ereignisse (Neujahr, Weihnachten). Sie können sie von jedem Teil Ihrer Anwendung aus ausführen (aufrufen).
//global variable
var a = 2;
//global function
function b(){
console.log(a); //access global variable
}
Wenn Sie in den USA sind, kennen Sie vielleicht Kim Kardashian, eine berüchtigte Berühmtheit (sie schafft es irgendwie, die Boulevardpresse zu machen). Aber Menschen außerhalb der USA werden sie nicht erkennen. Sie ist ein lokaler Star, der an ihr Territorium gebunden ist.
Lokale Variablen sind wie lokale Sterne. Sie können nur innerhalb des Gültigkeitsbereichs darauf zugreifen (den Wert abrufen oder festlegen). Eine lokale Funktion ist wie lokale Ereignisse - Sie können nur innerhalb dieses Bereichs ausführen (feiern). Wenn Sie von außerhalb des Bereichs darauf zugreifen möchten, wird ein Referenzfehler angezeigt
function b(){
var d = 21; //local variable
console.log(d);
function dog(){ console.log(a); }
dog(); //execute local function
}
console.log(d); //ReferenceError: dddddd is not defined
In diesem Artikel erfahren Sie mehr über den Geltungsbereich.
führen Sie den Code aus. Ich hoffe, dies gibt einen Eindruck über das Scoping
Name = 'global data';
document.Name = 'current document data';
(function(window,document){
var Name = 'local data';
var myObj = {
Name: 'object data',
f: function(){
alert(this.Name);
}
};
myObj.newFun = function(){
alert(this.Name);
}
function testFun(){
alert("Window Scope : " + window.Name +
"\nLocal Scope : " + Name +
"\nObject Scope : " + this.Name +
"\nCurrent document Scope : " + document.Name
);
}
testFun.call(myObj);
})(window,document);
Es gibt FAST nur zwei Arten von JavaScript-Bereichen:
Andere Blöcke als Funktionen erstellen also keinen neuen Gültigkeitsbereich. Das erklärt, warum for-Schleifen Variablen mit äußerem Gültigkeitsbereich überschreiben:
var i = 10, v = 10;
for (var i = 0; i < 5; i++) { var v = 5; }
console.log(i, v);
// output 5 5
Verwenden Sie stattdessen Funktionen:
var i = 10, v = 10;
$.each([0, 1, 2, 3, 4], function(i) { var v = 5; });
console.log(i,v);
// output 10 10
Im ersten Beispiel gab es keinen Blockbereich, daher wurden die ursprünglich deklarierten Variablen überschrieben. Im zweiten Beispiel gab es aufgrund der Funktion einen neuen Gültigkeitsbereich, sodass die ursprünglich deklarierten Variablen SHADOWED waren und nicht überschrieben wurden.
Das ist fast alles, was Sie in Bezug auf JavaScript-Scoping wissen müssen, außer:
Sie sehen also, dass das Scoping von JavaScript sehr einfach ist, wenn auch nicht immer intuitiv. Ein paar Dinge, die Sie beachten sollten:
Also dieser Code:
var i = 1;
function abc() {
i = 2;
var i = 3;
}
console.log(i); // outputs 1
ist äquivalent zu:
var i = 1;
function abc() {
var i; // var declaration moved to the top of the scope
i = 2;
i = 3; // the assignment stays where it is
}
console.log(i);
Dies mag kontraintuitiv erscheinen, ist aber aus Sicht eines imperativen Sprachdesigners sinnvoll.
const
' und 'let
'Wie bei den meisten anderen Hauptsprachen sollten Sie für jede von Ihnen erstellte Variable Block-Scoping verwenden. var
ist veraltet . Dies macht Ihren Code sicherer und wartbarer.
const
sollte für 95% der Fälle verwendet werden. Es macht es so, dass sich die Variable Referenz nicht ändern kann. Array-, Objekt- und DOM-Knoteneigenschaften können sich ändern und sollten wahrscheinlich const
lauten.
let
sollte für alle Variablen verwendet werden, die eine Neuzuweisung erwarten. Dies schließt innerhalb einer for-Schleife ein. Wenn Sie einen Wert über die Initialisierung hinaus ändern, verwenden Sie let
.
Gültigkeitsbereich blockieren bedeutet, dass die Variable nur in den Klammern verfügbar ist, in denen sie deklariert ist. Dies erstreckt sich auf interne Bereiche, einschließlich anonymer Funktionen, die in Ihrem Bereich erstellt wurden.
Es gibt nur Funktionsbereiche in JS. Gültigkeitsbereiche nicht blockieren! Sie können auch sehen, was hochgezogen wird.
var global_variable = "global_variable";
var hoisting_variable = "global_hoist";
// Global variables printed
console.log("global_scope: - global_variable: " + global_variable);
console.log("global_scope: - hoisting_variable: " + hoisting_variable);
if (true) {
// The variable block will be global, on true condition.
var block = "block";
}
console.log("global_scope: - block: " + block);
function local_function() {
var local_variable = "local_variable";
console.log("local_scope: - local_variable: " + local_variable);
console.log("local_scope: - global_variable: " + global_variable);
console.log("local_scope: - block: " + block);
// The hoisting_variable is undefined at the moment.
console.log("local_scope: - hoisting_variable: " + hoisting_variable);
var hoisting_variable = "local_hoist";
// The hoisting_variable is now set as a local one.
console.log("local_scope: - hoisting_variable: " + hoisting_variable);
}
local_function();
// No variable in a separate function is visible into the global scope.
console.log("global_scope: - local_variable: " + local_variable);
Nach meinem Verständnis gibt es drei Bereiche: globaler Bereich, global verfügbar; lokaler Geltungsbereich, der für eine gesamte Funktion unabhängig von Blöcken verfügbar ist; und Blockbereich, der nur für den Block, die Anweisung oder den Ausdruck verfügbar ist, für den er verwendet wurde. Der globale und lokale Bereich wird entweder innerhalb oder außerhalb einer Funktion mit dem Schlüsselwort 'var' angegeben, und der Blockbereich wird mit dem Schlüsselwort 'let' angegeben.
Für diejenigen, die glauben, dass es nur globalen und lokalen Geltungsbereich gibt, erklären Sie bitte, warum Mozilla eine ganze Seite haben würde, die die Nuancen des Block-Geltungsbereichs in JS beschreibt.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
Versuchen Sie dieses merkwürdige Beispiel. Wenn im folgenden Beispiel a eine Zahl mit 0 initialisiert wird, wird 0 und dann 1 angezeigt. Mit der Ausnahme, dass a ein Objekt ist und Javascript f1 als Zeiger von a und nicht als Kopie davon übergibt. Das Ergebnis ist, dass Sie beide Male dieselbe Warnung erhalten.
var a = new Date();
function f1(b)
{
b.setDate(b.getDate()+1);
alert(b.getDate());
}
f1(a);
alert(a.getDate());
In JavaScript gibt es zwei Arten von Gültigkeitsbereichen:
Die Funktion Below hat eine lokale Bereichsvariable carName
. Und auf diese Variable kann von außerhalb der Funktion nicht zugegriffen werden.
function myFunction() {
var carName = "Volvo";
alert(carName);
// code here can use carName
}
Die Below-Klasse hat eine globale Bereichsvariable carName
. Und auf diese Variable kann von überall in der Klasse zugegriffen werden.
class {
var carName = " Volvo";
// code here can use carName
function myFunction() {
alert(carName);
// code here can use carName
}
}
ES5
und früher:Variablen in Javascript waren anfangs (vor ES6
) lexikalisch funktionsspezifisch. Der Begriff "lexikalisch" bedeutet, dass Sie den Gültigkeitsbereich der Variablen durch "Betrachten" des Codes sehen können.
Jede Variable, die mit dem Schlüsselwort var
deklariert wurde, hat einen Gültigkeitsbereich für die Funktion. Wenn jedoch innerhalb dieser Funktion eine andere Funktion deklariert wird, haben diese Funktionen Zugriff auf die Variablen der äußeren Funktionen. Dies wird als Bereichskette bezeichnet. Es funktioniert auf folgende Weise:
// global scope
var foo = 'global';
var bar = 'global';
var foobar = 'global';
function outerFunc () {
// outerFunc scope
var foo = 'outerFunc';
var foobar = 'outerFunc';
innerFunc();
function innerFunc(){
// innerFunc scope
var foo = 'innerFunc';
console.log(foo);
console.log(bar);
console.log(foobar);
}
}
outerFunc();
Wenn wir versuchen, die Variablen foo
, bar
und foobar
in der Konsole zu protokollieren, geschieht Folgendes:
innerFunc
selbst gefunden werden. Daher wird der Wert von foo in die Zeichenfolge innerFunc
aufgelöst.innerFunc
selbst gefunden werden. Daher müssen wir die Scope-Kette erklimmen . Wir schauen uns zuerst die äußere Funktion an, in der die Funktion innerFunc
definiert wurde. Dies ist die Funktion outerFunc
. Im Geltungsbereich von outerFunc
finden wir den Variablenbalken, der den String 'outerFunc' enthält.ES6
(ES 2015) und älter:Die gleichen Konzepte von lexikalischem Geltungsbereich und Gültigkeitsbereich gelten auch in ES6
. Es wurden jedoch neue Methoden zur Deklaration von Variablen eingeführt. Es gibt folgende:
let
: Erstellt eine Variable mit Blockbereichconst
: Erstellt eine Blockbereichsvariable, die initialisiert werden muss und nicht neu zugewiesen werden kannDer größte Unterschied zwischen var
und let
/const
besteht darin, dass var
funktionsabhängig ist, während let
/const
blockabhängig sind. Hier ist ein Beispiel, um dies zu veranschaulichen:
let letVar = 'global';
var varVar = 'global';
function foo () {
if (true) {
// this variable declared with let is scoped to the if block, block scoped
let letVar = 5;
// this variable declared with let is scoped to the function block, function scoped
var varVar = 10;
}
console.log(letVar);
console.log(varVar);
}
foo();
Im obigen Beispiel protokolliert letVar den Wert global, da mit let
deklarierte Variablen blockbereichsabhängig sind. Sie existieren nicht mehr außerhalb des jeweiligen Blocks, sodass auf die Variable nicht außerhalb des if-Blocks zugegriffen werden kann.
ECMAScript 6 führte die Schlüsselwörter let und const ein. Diese Schlüsselwörter können anstelle des Schlüsselworts var verwendet werden. Im Gegensatz zum Schlüsselwort var unterstützen die Schlüsselwörter let und const die Deklaration des lokalen Bereichs in Blockanweisungen.
var x = 10
let y = 10
const z = 10
{
x = 20
let y = 20
const z = 20
{
x = 30
// x is in the global scope because of the 'var' keyword
let y = 30
// y is in the local scope because of the 'let' keyword
const z = 30
// z is in the local scope because of the 'const' keyword
console.log(x) // 30
console.log(y) // 30
console.log(z) // 30
}
console.log(x) // 30
console.log(y) // 20
console.log(z) // 20
}
console.log(x) // 30
console.log(y) // 10
console.log(z) // 10
In EcmaScript5 gibt es hauptsächlich zwei Bereiche: lokalen Bereich und globalen Bereich . In EcmaScript6 gibt es jedoch hauptsächlich drei Bereiche: lokalen Bereich, globalen Bereich und einen neuen Bereich namens Blockbereich .
Beispiel für einen Blockumfang:
for ( let i = 0; i < 10; i++)
{
statement1...
statement2...// inside this scope we can access the value of i, if we want to access the value of i outside for loop it will give undefined.
}