wake-up-neo.com

Was ist der Gültigkeitsbereich von Variablen in JavaScript?

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?

1918
lYriCAlsSH

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.

  1. Eine Variable mit globalem Gültigkeitsbereich

    // global scope
    var a = 1;
    
    function one() {
      alert(a); // alerts '1'
    }
    
  2. 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'
    }
    
  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
    }
    
  4. Intermediate : Objekteigenschaften

    var a = 1;
    
    function Five() {
      this.a = 5;
    }
    
    alert(new Five().a); // alerts '5'
    
  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'
      };
    })();
    
  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'
    

  7. 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); 
    })();
    
  8. 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.

2447
Triptych

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.

232
krosenvold

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.)

107
Jon Skeet

Alte Schule JavaScript

Traditionell gibt es in JavaScript nur zwei Arten von Gültigkeitsbereichen:

  1. Global Scope : Variablen sind in der gesamten Anwendung vom Start der Anwendung an bekannt (*)
  2. Funktionsumfang : Variablen sind in der Funktion bekannt sie werden vom Beginn der Funktion an (* )

Ich werde darauf nicht näher eingehen, da es bereits viele andere Antworten gibt, die den Unterschied erklären.


Modernes JavaScript

Die neuesten JavaScript-Spezifikationen erlauben jetzt auch einen dritten Bereich:

  1. Block Scope : Variablen sind in dem Block bekannt sie werden in dem Moment deklariert, in dem sie deklariert werden ( **)

Wie erstelle ich Blockbereichsvariablen?

Traditionell erstellen Sie Ihre Variablen folgendermaßen:

var myVariable = "Some text";

Blockbereichsvariablen werden folgendermaßen erstellt:

let myVariable = "Some text";

Was ist also der Unterschied zwischen Funktionsumfang und Blockumfang?

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.


Ist es heute sicher, Blockbereichsvariablen zu verwenden?

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:

    • Internet Explorer 10 und darunter
    • Firefox 43 und darunter
    • Safari 9 und darunter
    • Android Browser 4 und darunter
    • Opera 27 und darunter
    • Chome 40 und darunter
    • JEDE Version von Opera Mini & Blackberry Browser

enter image description here


So behalten Sie den Überblick über die Browser-Unterstützung

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

74
John Slegers

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.

38
geowa4

Der Schlüssel, wie ich es verstehe, ist, dass Javascript das Scoping auf Funktionsebene gegenüber dem allgemeineren C-Block-Scoping hat.

Hier ist ein guter Artikel zu diesem Thema.

31
James McMahon

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
26
kennytm

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

  • Bereiche sind technisch "Ausführungskontexte"
  • Kontexte bilden einen Stapel von Umgebungen, in denen Variablen gespeichert werden
  • Die Oberseite des Stapels hat Vorrang (die Unterseite ist der globale Kontext)
  • Jede Funktion erstellt einen Ausführungskontext (diese Bindung ist jedoch nicht immer neu).

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.

enter image description here

23
Travis J

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.

17
Gerard ONeill

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.

10
austincheney

JavaScript hat nur zwei Arten von Gültigkeitsbereichen:

  1. Globaler Bereich: Global ist nichts anderes als ein Bereich auf Fensterebene. Hier eine Variable, die in der gesamten Anwendung vorhanden ist.
  2. Funktionsumfang: Die in einer Funktion mit dem Schlüsselwort 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 ->

  1. Fensterebene - Die Funktionen a und outer befinden sich in der Scope-Kette auf der obersten Ebene.
  2. wenn die äußere Funktion einen neuen 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.

9
Anshul

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:

image

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

9
James Drinkard

Globaler Geltungsbereich:

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
}

Lokaler Geltungsbereich:

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.

8
KhanSharp

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

Es gibt FAST nur zwei Arten von JavaScript-Bereichen:

  • der Umfang jeder var-Deklaration ist mit der am unmittelbarsten umschließenden Funktion verknüpft
  • wenn es keine einschließende Funktion für eine var-Deklaration gibt, handelt es sich um einen globalen Bereich

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:

  • var-Deklarationen werden an die Spitze des Geltungsbereichs gehievt. Dies bedeutet, egal wo die var-Deklaration vorkommt, für den Compiler ist es so, als würde die var selbst oben vorkommen
  • mehrere var-Deklarationen innerhalb desselben Gültigkeitsbereichs werden kombiniert

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.

6
jackbean818

Modern Js, ES6 +, '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.

5
Gibolt

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);
4
koredalin

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

3
mrmaclean89

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

In JavaScript gibt es zwei Arten von Gültigkeitsbereichen:

  • Lokaler Geltungsbereich
  • Globaler Geltungsbereich

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 
    }
}
2
Abdur Rahman

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:

  1. Wenn eine Funktion versucht, einen Variablenwert aufzulösen, untersucht sie zunächst ihren eigenen Gültigkeitsbereich. Dies ist der Funktionskörper, dh alles zwischen geschweiften Klammern {} (außer Variablen in anderen Funktionen die in diesem Bereich liegen).
  2. Wenn die Variable im Funktionskörper nicht gefunden werden kann, steigt sie auf die Kette und zeigt den Gültigkeitsbereich der Variablen in der Funktion in wo die Funktion definiert wurde . Dies ist, was mit lexikalischem Gültigkeitsbereich gemeint ist, wir können in dem Code sehen, wo diese Funktion definiert wurde, und können somit die Gültigkeitsbereichskette bestimmen, indem wir nur den Code betrachten.

Beispiel:

// 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:

  1. Wir versuchen, foo in die Konsole einzuloggen, foo kann in der Funktion innerFunc selbst gefunden werden. Daher wird der Wert von foo in die Zeichenfolge innerFunc aufgelöst.
  2. Wir versuchen, die Leiste in die Konsole einzuloggen. Die Leiste kann nicht in der Funktion 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.
  3. foobar kann in innerFunc nicht gefunden werden. . Daher müssen wir die Scope-Kette zum InnerFunc-Scope hochklettern. Es kann auch hier nicht gefunden werden, wir klettern eine andere Ebene in den globalen Bereich (d. H. Den äußersten Bereich). Wir finden hier die Variable foobar, die den String 'global' enthält. Wenn die Variable nach dem Durchlaufen der Scope-Kette nicht gefunden worden wäre, würde die JS-Engine einen referenceError auslösen.

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 Blockbereich
  • const: Erstellt eine Blockbereichsvariable, die initialisiert werden muss und nicht neu zugewiesen werden kann

Der 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.

1

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
1
Dava

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.
}
1
Vivek Mehta