Scoping und Heben der Javascript-Funktion


89

Ich habe gerade einen großartigen Artikel über JavaScript Scoping und Hoisting von Ben Cherry gelesen, in dem er das folgende Beispiel gibt:

var a = 1;

function b() {
    a = 10;
    return;

    function a() {}
}
b();
alert(a);

Mit dem obigen Code alarmiert der Browser "1".

Ich bin mir immer noch nicht sicher, warum es "1" zurückgibt. Einige der Dinge, die er sagt, kommen in den Sinn wie: Alle Funktionsdeklarationen werden nach oben gehoben. Sie können eine Variable mit der Funktion erfassen. Klickt immer noch nicht für mich.

Antworten:


120

Funktionsheben bedeutet, dass Funktionen an die Spitze ihres Bereichs verschoben werden. Das ist,

function b() {  
   a = 10;  
   return;  
   function a() {} 
} 

wird vom Interpeter dazu umgeschrieben

function b() {
  function a() {}
  a = 10;
  return;
}

Seltsam, was?

Auch in diesem Fall

function a() {}

benahm sich genauso wie

var a = function () {};

Im Wesentlichen macht der Code Folgendes:

var a = 1;                 //defines "a" in global scope
function b() {  
   var a = function () {}; //defines "a" in local scope 
   a = 10;                 //overwrites local variable "a"
   return;      
}       
b();       
alert(a);                 //alerts global variable "a"

2
Also werden alle Funktionsdeklarationen schließlich einer Variablen zugewiesen?
dev.e.loper

15
@ dev.e.loper Ja, in Javascript sind Funktionen erstklassige Objekte, genau wie Zeichenfolgen und Zahlen. Das heißt, sie sind als Variablen definiert und können an andere Funktionen übergeben, in Arrays gespeichert usw. werden.
Peter Olson

4
Der Funktionskörper wird in keiner Weise "umgeschrieben". In den verschiedenen ECMAScript-Standards ist eindeutig festgelegt, dass Variablen- und Funktionsdeklarationen verarbeitet werden, bevor die Codeausführung beginnt. Das heißt, nichts wird bewegt , es geht um die Reihenfolge der Ausführung (daher meine Abneigung gegen den Begriff "Heben", der auf Bewegung oder Neuordnung schließen lässt). In Ihrem neu geschriebenen Code sollte die Deklaration var avor der Funktionsdeklaration und die Zuweisung a = 1nach sein. Beachten Sie jedoch, dass dies nicht vom Parser, Tokeniser, Interpreter, Compiler angegeben wird. Es ist nur ein Äquivalent.
RobG

3
@RobG Sicher, ich denke, Sie könnten die Beschreibung eine kleine "Lüge für Kinder" nennen , aber am Ende ist das Verhalten das gleiche, unabhängig davon, ob der Code buchstäblich neu angeordnet wird oder nur die Reihenfolge der Ausführung neu angeordnet wird. Was tatsächlich hinter den Kulissen passiert, ist eher ein akademisches Problem und kann sogar von der Implementierung abhängen.
Peter Olson

7
"Auch in diesem Fall hat function a() {}sich das gleiche verhalten wie var a = function () {};"  - dies ist in zweierlei Hinsicht falsch: Erstens, wenn überhaupt, wäre es gewesen var a = function a() {};(die Funktion ist eigentlich nicht anonym), zweitens sind diese beiden Formen nicht austauschbar, weil von var a = function a() {};nur das var a;Teil wäre gehisst worden. Der a = function a() {};Teil wäre immer noch hinter der Rückgabeerklärung gewesen. Da das ursprüngliche Formular eine Funktionsdeklaration und kein Funktionsausdruck ist, wird es tatsächlich als Ganzes hochgezogen.
user4642212

6

Was Sie beachten müssen, ist, dass es die gesamte Funktion analysiert und alle Variablendeklarationen auflöst, bevor es ausgeführt wird. So....

function a() {} 

wird wirklich

var a = function () {}

var a Erzwingt es in einen lokalen Bereich, und der Variablenbereich erstreckt sich über die gesamte Funktion. Die globale Variable a ist also immer noch 1, da Sie a in einen lokalen Bereich deklariert haben, indem Sie es zu einer Funktion gemacht haben.


5

Die Funktion awird innerhalb der Funktion gehisst b:

var a = 1; 
function b() { 
   function a() {} 
   a = 10; 
   return;
} 
b(); 
alert(a);

das ist fast wie mit var:

var a = 1; 
function b() { 
   var a = function () {};
   a = 10; 
   return;
} 
b(); 
alert(a);

Die Funktion wird lokal deklariert, und die Einstellung erfolgt anur im lokalen Bereich, nicht im globalen var.


1
Diese Zeile "var a = function () {};" macht alles klar. Grundsätzlich ist JavaScript eine dynamische Sprache und "function" ist auch ein Objekt in JavaScript.
Refactor

3
  1. Die Funktionsdeklaration function a(){}wird zuerst gehisst und verhält sich wie folgt var a = function () {};, daher wird im lokalen Bereich aerstellt.
  2. Wenn Sie zwei Variablen mit demselben Namen haben (eine global und eine lokal), hat die lokale Variable immer Vorrang vor der globalen Variablen.
  3. Wenn Sie festlegen a=10, legen Sie die lokale Variable fest a, nicht die globale.

Daher bleibt der Wert der globalen Variablen gleich und Sie erhalten eine Warnung 1


1

function a() { }ist eine Funktionsanweisung, die eine alokale Variable für die bFunktion erstellt.
Variablen werden erstellt, wenn eine Funktion analysiert wird, unabhängig davon, ob die varAnweisung oder ausgeführt wird.

a = 10 setzt diese lokale Variable.


Setzt tatsächlich a = 10eine Variable im globalen Bereich, wenn die Funktion bausgeführt wird, sofern Sie nichts hinzufügen "use strict"(in Umgebungen, die diese Anweisung unterstützen).
Sean Vieira

@ Sean: Nein, da die Funktionsanweisung einen lokalen Bezeichner erstellt.
SLaks

... und ... du hast recht. Hatte diese besondere Konsequenz des Funktionshebens nicht erkannt. Vielen Dank!
Sean Vieira

1

Was ist der Streitpunkt in diesem kleinen Codeausschnitt?

Fall 1:

Fügen Sie die function a(){}Definition function bwie folgt in den Körper ein .logs value of a = 1

var a = 1;
function b() {
  a = 10;
  return;

  function a() {}
}
b();
console.log(a); // logs a = 1

Fall 2

Schließen Sie die function a(){}Definition innerhalb des Körpers function bwie folgt aus.logs value of a = 10

var a = 1;
function b() {
  a = 10;  // overwrites the value of global 'var a'
  return;
}
b();
console.log(a); // logs a = 10

Durch Beobachtung können Sie erkennen, dass die Anweisung console.log(a)die folgenden Werte protokolliert.

Fall 1: a = 1

Fall 2: a = 10

Posits

  1. var a wurde im globalen Bereich lexikalisch definiert und deklariert.
  2. a=10 Diese Anweisung weist den Wert 10 neu zu und befindet sich lexikalisch in der Funktion b.

Erklärung beider Fälle

Wegen function definition with name propertya ist das gleiche wie das variable a. Das variable aInnere function body bwird zu einer lokalen Variablen. Die vorherige Zeile impliziert, dass der globale Wert von a intakt bleibt und der lokale Wert von a auf 10 aktualisiert wird.

Wir wollen also sagen, dass der folgende Code

var a = 1;
function b() {
  a = 10;
  return;

  function a() {}
}
b();
console.log(a); // logs a = 1

Es wird vom JS-Interpreter wie folgt interpretiert.

var a = 1;
function b() {
  function a() {}
  a = 10;
  return;


}
b();
console.log(a); // logs a = 1

Wenn wir jedoch die entfernen function a(){} definition, die value of 'a'erklärt und außerhalb der Funktion b definiert ist , wird dieser Wert überschrieben und es ändert sich auf 10 bei 2. Der Wert überschrieben wird , weil a=10auf die globale Erklärung bezieht , und wenn sie deklariert werden sollten lokal müssen wir haben geschrieben var a = 10;.

var a = 1;
function b() {
  var a = 10; // here var a is declared and defined locally because it uses a var keyword. 
  return;
}
b();
console.log(a); // logs a = 1

Wir können unsere Zweifel weiter klären, indem wir das name propertyIn function a(){} definitionin einen anderen Namen als ändern'a'

var a = 1;
function b() {
  a = 10; // here var a is declared and defined locally because it uses a var keyword. 
  return;

  function foo() {}
}
b();
console.log(a); // logs a = 1

1

Heben ist ein Konzept, das für uns entwickelt wurde, um das Verständnis zu erleichtern. Was tatsächlich passiert, ist, dass die Deklarationen zuerst in Bezug auf ihren Geltungsbereich erfolgen und die Zuweisungen danach erfolgen (nicht gleichzeitig).

Wenn die Deklarationen stattfinden, var awird function bund innerhalb dieses bBereichs function adeklariert.

Diese Funktion a schattiert die Variable a aus dem globalen Bereich.

Nachdem die Deklarationen abgeschlossen sind, beginnen die zugewiesenen Werte, der globale aerhält den Wert 1und das a inside function bwird erhalten 10. Wenn Sie dies tun alert(a), wird die tatsächliche globale Bereichsvariable aufgerufen. Diese kleine Änderung am Code wird es klarer machen

        var a = 1;

    function b() {
        a = 10;
        return a;

        function a() { }
    }

    alert(b());
    alert(a);

1
Es ist merkwürdig, dass sich so viele Experten selbst in einem Kurs auf codeschool.com auf das Heben beziehen, was nichts anderes als eine vereinfachte Ansicht dessen ist, was passiert. Tatsächlich geschieht das Heben überhaupt nicht. Ref: 1) developer.mozilla.org/en-US/docs/Glossary/Hoisting 2) Kapitel 5 der Geheimnisse des JavaScript Ninja 2 / e von John Resig, Bear Bebeault, Josip Maras
Adnan2nd

1

Überraschenderweise erwähnt keine der Antworten hier die Relevanz des Ausführungskontexts in der Scope-Kette.

Die JavaScript Engine umschließt den aktuell ausgeführten Code mit einem Ausführungskontext. Der Basisausführungskontext ist der globale Ausführungskontext. Jedes Mal, wenn eine neue Funktion aufgerufen wird, wird ein neuer Ausführungskontext erstellt und auf den Ausführungsstapel gelegt. Stellen Sie sich einen Stapelrahmen vor, der in anderen Programmiersprachen auf einem Aufrufstapel sitzt. Zuletzt rein, zuerst raus. Jetzt hat jeder Ausführungskontext seine eigene variable Umgebung und äußere Umgebung in JavaScript.

Ich werde das folgende Beispiel als Demonstration verwenden.

1) Zuerst treten wir in die Erstellungsphase des globalen Ausführungskontexts ein. Sowohl die äußere als auch die variable Umgebung der lexikalischen Umgebung werden erstellt. Das globale Objekt wird eingerichtet und im Speicher abgelegt, wobei die spezielle Variable 'this' darauf zeigt. Die Funktion a und ihr Code sowie die Variable myVar mit einem undefinierten Wert werden in der globalen Variablenumgebung gespeichert. Es ist wichtig zu beachten, dass der Code der Funktion a nicht ausgeführt wird. Es wird nur mit der Funktion a gespeichert.

2) Zweitens ist es die Ausführungsphase des Ausführungskontexts. myVar ist kein undefinierter Wert mehr. Es wird mit dem Wert 1 initialisiert, der in der globalen Variablenumgebung gespeichert ist. Die Funktion a wird aufgerufen und ein neuer Ausführungskontext erstellt.

3) Im Ausführungskontext der Funktion a durchläuft sie die Erstellungs- und Ausführungsphase ihres eigenen Ausführungskontexts. Es hat eine eigene äußere Umgebung und eine variable Umgebung, also eine eigene lexikalische Umgebung. Die Funktion b und die Variable myVar werden in ihrer Variablenumgebung gespeichert. Diese variable Umgebung unterscheidet sich von der globalen variablen Umgebung. Da sich die Funktion a lexikalisch (physisch im Code) auf derselben Ebene wie der globale Ausführungskontext befindet, ist ihre äußere Umgebung der globale Ausführungskontext. Wenn sich die Funktion a auf eine Variable beziehen soll, die sich nicht in ihrer Variablenumgebung befindet, durchsucht sie die Bereichskette und versucht, die Variable in der Variablenumgebung des globalen Ausführungskontexts zu finden.

4) Die Funktion b wird in Funktion a aufgerufen. Ein neuer Ausführungskontext wird erstellt. Da es in Funktion a lexikalisch sitzt, ist seine äußere Umgebung a. Wenn also auf myVar verwiesen wird, da myVar nicht in der variablen Umgebung von Funktion b enthalten ist, wird es in der variablen Umgebung von Funktion a angezeigt. Es findet es dort und console.log druckt 2. Wenn sich die Variable jedoch nicht in der Variablenumgebung von Funktion a befand, wird die Bereichskette dort weiter suchen, da die äußere Umgebung von Funktion a der globale Ausführungskontext ist.

5) Nachdem die Ausführung von Funktion b und a abgeschlossen ist, werden sie aus dem Ausführungsstapel entfernt. Die Single-Threaded-JavaScript-Engine setzt die Ausführung im globalen Ausführungskontext fort. Es ruft die Funktion b auf. In der globalen Variablenumgebung gibt es jedoch keine b-Funktion und im globalen Ausführungskontext keine andere äußere Umgebung, nach der gesucht werden kann. Daher wird von der JavaScript Engine eine Ausnahme ausgelöst.

function a(){
  function b(){
    console.log(myVar);
  }

  var myVar = 2;
  b();
}

var myVar = 1;
a();
b();
> 2
> Uncaught ReferenceError: b is not defined

Das folgende Beispiel zeigt die Scope Chain in Aktion. In der Variablenumgebung des Ausführungskontexts der Funktion b gibt es kein myVar. Also durchsucht es seine äußere Umgebung, die die Funktion a ist. Die Funktion a hat myVar auch nicht in ihrer variablen Umgebung. Die Suchmaschinenfunktion funktioniert also mit der äußeren Umgebung von a, der äußeren Umgebung des globalen Ausführungskontexts, und myVar ist dort definiert. Daher gibt das console.log 1 aus.

function a(){
  function b(){
    console.log(myVar);
  }

  b();
}

var myVar = 1;
a();
> 1

In Bezug auf den Ausführungskontext und die damit verbundene lexikalische Umgebung, einschließlich der äußeren Umgebung und der Variablenumgebung, können Sie Variablen in JavaScript festlegen. Selbst wenn Sie dieselbe Funktion mehrmals aufrufen, wird für jeden Aufruf ein eigener Ausführungskontext erstellt. Jeder Ausführungskontext verfügt also über eine eigene Kopie der Variablen in seiner Variablenumgebung. Es gibt keine gemeinsame Nutzung von Variablen.



0

Hier ist meine Zusammenfassung der Antwort mit mehr Anmerkungen und einer begleitenden Geige, mit der ich herumspielen kann.

// hoisting_example.js

// top of scope ie. global var a = 1
var a = 1;

// new scope due to js' functional (not block) level scope
function b() {
    a = 10; // if the function 'a' didn't exist in this scope, global a = 10
  return; // the return illustrates that function 'a' is hoisted to top
  function a(){}; // 'a' will be hoisted to top as var a = function(){};
}

// exec 'b' and you would expect to see a = 10 in subsequent alert
// but the interpreter acutally 'hoisted' the function 'a' within 'b' 
// and in doing so, created a new named variable 'a' 
// which is a function within b's scope
b();

// a will alert 1, see comment above
alert(a);

https://jsfiddle.net/adjavaherian/fffpxjx7/


0

Scpope & Closure & Heben (Var / Funktion)

  1. scpope: Auf die globale Variable kann an jedem Ort zugegriffen werden (auf den gesamten Dateibereich), auf die lokale Variable kann nur über den lokalen Bereich zugegriffen werden (Funktions- / Blockbereich)!
    Hinweis: Wenn eine lokale Variable keine var-Schlüsselwörter in einer Funktion verwendet, wird sie zu einer globalen Variablen!
  2. Closure: Eine Funktion innerhalb der anderen Funktion, die auf den lokalen Bereich (übergeordnete Funktion) und den globalen Bereich zugreifen kann. Wie auch immer, auf die Variablen kann nicht von anderen zugegriffen werden! es sei denn, Sie geben es als Rückgabewert zurück!
  3. Heben: Verschieben Sie alle deklarierten / nicht deklarierten Variablen / Funktionen nach oben, und weisen Sie dann den Wert oder null zu!
    Hinweis: Es wird nur die Deklaration verschoben, nicht der Wert!

var a = 1;                
//"a" is global scope
function b() {  
   var a = function () {}; 
   //"a" is local scope 
   var x = 12; 
   //"x" is local scope 
   a = 10;
   //global variable "a" was overwrited by the local variable "a"  
   console.log("local a =" + a);
   return console.log("local x = " + x);
}       
b();
// local a =10
// local x = 12
console.log("global a = " + a);
// global a = 1
console.log("can't access local x = \n");
// can't access local x = 
console.log(x);
// ReferenceError: x is not defined



0

Heben In JavaScript werden Variablendeklarationen im gesamten Programm ausgeführt, bevor Code ausgeführt wird. Das Deklarieren einer Variablen an einer beliebigen Stelle im Code entspricht daher dem Deklarieren am Anfang.


0

Alles hängt vom Umfang der Variablen 'a' ab. Lassen Sie mich erklären, indem Sie Bereiche als Bilder erstellen.

Hier erstellt JavaScript 3 Bereiche.

i) Globaler Geltungsbereich. ii) Funktionsumfang b (). iii) Funktion a () Umfang.

Geben Sie hier die Bildbeschreibung ein

Es ist klar, wenn Sie den Methodenbereich 'alert' aufrufen, der zu diesem Zeitpunkt zu Global gehört. Daher wird der Wert der Variablen 'a' nur aus dem globalen Bereich ausgewählt, der 1 ist.


0

Langer Beitrag!

Aber es wird die Luft reinigen!

Java Script funktioniert in zwei Schritten:

  1. Kompilierung (sozusagen) - In diesem Schritt werden Variablen und Funktionsdeklarationen sowie deren jeweiliger Umfang registriert. Es geht nicht darum, den Funktionsausdruck var a = function(){}oder den Variablenausdruck zu bewerten (wie das Zuweisen 3zu, xwenn var x =3;dies nichts anderes ist als die Bewertung des RHS-Teils).

  2. Interpreter: Dies ist der Ausführungs- / Bewertungsteil.

Überprüfen Sie die Ausgabe des folgenden Codes, um ein Verständnis zu erhalten:

//b() can be called here!
//c() cannot be called.
console.log("a is " + a);
console.log("b is " + b);
console.log("c is " + c);
var a = 1;
console.log("Now, a is " + a);
var c = function() {};
console.log("Now c is " + c);

function b() {
  //cannot write the below line:
  //console.log(e); 
  //since e is not declared.
  e = 10; //Java script interpreter after traversing from this function scope chain to global scope, is unable to find this variable and eventually initialises it with value 10 in global scope.
  console.log("e is " + e) //  works!
  console.log("f is " + f);
  var f = 7;
  console.log("Now f is " + f);
  console.log("d is " + d);
  return;

  function d() {}
}
b();
console.log(a);

Lass es uns brechen:

  1. In der Kompilierungsphase würde 'a' im globalen Bereich mit dem Wert ' undefined' registriert . Gleiches gilt für ' c', sein Wert wäre in diesem Moment ' undefined' und nicht das ' function()'. ' b' würde als Funktion im globalen Bereich registriert. Innerhalb bdes Gültigkeitsbereichs fwürde ' ' als eine Variable registriert, die zu diesem Zeitpunkt undefiniert wäre, und die Funktion ' d' würde registriert.

  2. Wenn der Interpreter ausgeführt wird, kann auf deklarierte Variablen und function()(und nicht auf Ausdrücke) zugegriffen werden, bevor der Interpreter die tatsächliche Ausdruckszeile erreicht. Variablen würden also ' undefined' gedruckt und deklarierte anonyme Funktionen können früher aufgerufen werden. Der Versuch, vor der Initialisierung des Ausdrucks auf eine nicht deklarierte Variable zuzugreifen, führt jedoch zu einem Fehler wie:

console.log(e)
e = 3;

Was passiert nun, wenn Sie eine Variablen- und Funktionsdeklaration mit demselben Namen haben?

Die Antwort lautet : Funktionen werden immer vorher gehisst. Wenn dieselbe Namensvariable deklariert wird, wird sie als doppelt behandelt und ignoriert. Denken Sie daran, Reihenfolge spielt keine Rolle. Funktionen haben immer Vorrang. Während der Evaluierungsphase können Sie die Variablenreferenz jedoch auf alles ändern (sie speichert die letzte Zuordnung). Sehen Sie sich den folgenden Code an:

var a = 1;
console.log("a is " + a);

function b() {
  console.log("a inside the function b is " + a); //interpreter finds                                'a' as function() in current scope. No need to go outside the scope to find 'a'.
  a = 3; //a changed
  console.log("Now a is " + a);
  return;

  function a() {}
}
var a; //treated as duplicate and ignored.
b();
console.log("a is still " + a + " in global scope"); //This is global scope a.


0

Heben ist ein Verhaltenskonzept von JavaScript. Heben (z. B. Bewegen) ist ein Konzept, das erklärt, wie und wo Variablen deklariert werden sollen.

In JavaScript kann eine Variable nach ihrer Verwendung deklariert werden, da Funktionsdeklarationen und Variablendeklarationen vom JavaScript-Interpreter immer unsichtbar an den Anfang ihres enthaltenen Bereichs verschoben ("gehisst") werden.

In den meisten Fällen gibt es zwei Arten des Hebens.

1.Variable Deklaration Heben

Lassen Sie uns dies unter diesem Code verstehen.

 a = 5; // Assign 5 to a
 elem = document.getElementById("demo"); // Find an element 
 elem.innerHTML = a;                     // Display a in the element
 var a; // Declare a
  //output-> 5

Hier wird die Deklaration der Variablen a vom Javascript-Interpreter zum Zeitpunkt der Kompilierung unsichtbar nach oben gehostet. So konnten wir Wert von a bekommen. Dieser Ansatz der Deklaration von Variablen wird jedoch nicht empfohlen, da wir Variablen bereits so nach oben deklarieren sollten.

 var a = 5; // Assign and declare 5 to a
 elem = document.getElementById("demo"); // Find an element 
 elem.innerHTML = a;                     // Display a in the element
  // output -> 5

Betrachten Sie ein anderes Beispiel.

  function foo() {
     console.log(x)
     var x = 1;
 }

wird tatsächlich so interpretiert:

  function foo() {
     var x;
     console.log(x)
     x = 1;
  }

In diesem Fall ist x undefiniert

Es spielt keine Rolle, ob der Code ausgeführt wurde, der die Deklaration der Variablen enthält. Betrachten Sie dieses Beispiel.

  function foo() {
     if (false) {
         var a = 1;
     }
     return;
     var b = 1;
  }

Diese Funktion stellt sich als solche heraus.

  function foo() {
      var a, b;
      if (false) {
        a = 1;
     }
     return;
     b = 1;
  }

In der Variablendeklaration werden nur Hebezeuge mit variabler Definition verwendet, nicht die Zuordnung.

  1. Heben der Funktionsdeklaration

Im Gegensatz zum variablen Heben wird auch der Funktionskörper oder der zugewiesene Wert gehisst. Betrachten Sie diesen Code

 function demo() {
     foo(); // this will give error because it is variable hoisting
     bar(); // "this will run!" as it is function hoisting
     var foo = function () {
         alert("this would not run!!");
     }
     function bar() { 
         alert("this will run!!");
     }
 }
 demo();

Nachdem wir nun sowohl das Heben von Variablen als auch von Funktionen verstanden haben, wollen wir diesen Code jetzt verstehen.

var a = 1;
function b() {
  a = 10;
  return;
   function a() {}
}
b();
alert(a);

Dieser Code wird sich als solcher herausstellen.

var a = 1;                 //defines "a" in global scope
 function b() {  
   var a = function () {}; //defines "a" in local scope 
    a = 10;                 //overwrites local variable "a"
    return;      
 }       
 b();       
 alert(a); 

Die Funktion a () hat einen lokalen Gültigkeitsbereich innerhalb von b (). a () wird nach oben verschoben, während der Code mit seiner Definition interpretiert wird (nur im Fall von Funktionserhöhungen), sodass a jetzt einen lokalen Bereich hat und daher den globalen Bereich von a nicht beeinflusst, während es einen eigenen Bereich innerhalb der Funktion b () hat. .


0

Nach meinem Wissen geschieht das Heben mit der Variablendeklaration und der Funktionsdeklaration, zum Beispiel:

a = 7;
var a;
console.log(a) 

Was passiert in der JavaScript-Engine:

var a;
a = 7;
console.log(a);
// 7

Oder:

console.log(square(7)); // Output: 49
function square(n) { return n * n; }

Es wird werden:

function square(n) { return n * n; }
console.log(square(7)); // 49

Zuweisungen wie die Zuweisung von Variablen oder die Zuweisung von Funktionsausdrücken werden jedoch nicht gehisst: Zum Beispiel:

console.log(x);
var x = 7; // undefined

Es kann so werden:

var x;
console.log(x); // undefined
x = 7;

0

Um das Hosting in Javascript in einem Satz zu beschreiben, werden Variablen und Funktionen an die Spitze des Bereichs angehoben, in dem sie deklariert sind.

Geben Sie hier die Bildbeschreibung ein

Ich gehe davon aus, dass Sie ein Anfänger sind. Um das Heben zuerst richtig zu verstehen, haben wir den Unterschied zwischen undefiniert und ReferenceError verstanden

 var v;
 console.log(v);
 console.log(abc);
/*
The output of the above codes are:
undefined
ReferenceError: abc is not defined*/

Was sehen wir jetzt im folgenden Code? Eine Variable und ein Funktionsausdruck werden deklariert.

<script>
var totalAmo = 8;
var getSum = function(a, b){
      return a+b;
}
</script>

aber das wirkliche Bild mit dem Beweis, dass sowohl die Variable als auch die Funktion oben in ihrem Bereich angehoben sind:

console.log(totalAmo);
console.log(getSum(8,9));
var totalAmo = 8;
var getSum = function(a, b){
      return a+b;
}
console.log(totalAmo);
console.log(getSum(9,7));

Die Ausgabe der ersten beiden Protokolle ist undefiniert und TypeError: getSum ist keine Funktion, da sowohl var totalAmo als auch getSum wie unten oben in ihrem Bereich angezeigt werden

 <script>
        var totalAmo;
        var getSum;

        console.log(totalAmo);
        console.log(getSum(8,9));
        var totalAmo = 8;
        var getSum = function(a, b){
            return a+b;
        }
        console.log(totalAmo);
        console.log(getSum(9,7));
    </script>

Bei der Funktionsdeklaration werden jedoch ganze Funktionen über ihren Geltungsbereich angehoben.

console.log(getId());
function getId(){
   return 739373;
}
/* output: 739373, because the whole function hoisted on the top of the scope.*/

Dieselbe Logik gilt nun für die Varibale, Funktionserfahrungen und Funktionsdeklarationen, die innerhalb des Funktionsumfangs deklariert wurden. Wichtigster Punkt: Sie werden nicht oben in die Datei gehievt .

function functionScope(){
            var totalAmo;
            var getSum;

            console.log(totalAmo);
            console.log(getSum(8,9));
            var totalAmo = 8;
            var getSum = function(a, b){
                return a+b;
            }
        }

Wenn Sie also das Schlüsselwort var verwenden , werden Variable und Funktion oben im Bereich des Bereichs (globaler Bereich und Funktionsbereich) angezeigt. Was ist mit let und const , const und let sind sich immer noch des globalen Bereichs und des Funktionsbereichs bewusst, genau wie var, aber const- und let-Variablen kennen auch einen anderen Bereich, der als blockierter Bereich bezeichnet wird. Ein Blockbereich ist immer dann vorhanden, wenn ein Codeblock vorhanden ist, z. B. for-Schleife, if else-Anweisung, while-Schleife usw.

Wenn wir const und let verwenden, um eine Variable in diesem Blockbereich zu deklarieren, wird die Variablendeklaration nur über dem Block angehoben, in dem sie sich befindet, und nicht über der übergeordneten Funktion oder über dem globaler Umfang, dass es gehisst wird.

 function getTotal(){
            let total=0;
            for(var i = 0; i<10; i++){
                let valueToAdd = i;
                var multiplier = 2;
                total += valueToAdd*multiplier;
            }
            return total;
        }

Variablen im Abobe-Beispiel werden wie unten angehoben

 function getTotal(){
            let total;
            var multiplier;
            total = 0;
            for(var i = 0; i<10; i++){
                let valueToAdd;
                valueToAdd = i;
                multiplier = 2;
                total += valueToAdd*multiplier;
            }
            return total;
        }

0

ES5: Funktionsheben & variables Heben

function hoistingPriorität ist greateralsvariable hoisting

"use strict";

/**
 *
 * @author xgqfrms
 * @license MIT
 * @copyright xgqfrms
 * @created 2016-06-01
 * @modified
 *
 * @description function-hoisting.js
 * @augments
 * @example
 * @link
 *
 */

(function() {
  const log = console.log;

  var a = 1;
  function b() {
    a = 10;
    log(`local a`, a)
    return;
    // function hoisting priority is greater than variable hoisting
    function a() {}
  }
  b();
  log(`global a`, a);
  // local a 10
  // global a 1
})();


das ist gleich

(function() {
  const log = console.log;

  // define "a" in global scope
  var a = 1;
  function b() {
    // define "a" in local scope
    var a ;
    // assign function to a
    a = function () {};
    // overwrites local variable "a"
    a = 10;
    log(`local a`, a);
    return;
  }

  b();
  // log global variable "a"
  log(`global a`, a);

  // local a 10
  // global a 1
})();

der Grund für das Heben

var a = 1;                
//"a" is global scope
function b() {  
   var a = function () {}; 
   //"a" is local scope 
   var x = 12; 
   //"x" is local scope 
   a = 10;
   //global variable "a" was overwrited by the local variable "a"  
   console.log("local a =" + a);
   return console.log("local x = " + x);
}       
b();
// local a =10
// local x = 12
console.log("global a = " + a);
// global a = 1
console.log("can't access local x = \n");
// can't access local x = 
console.log(x);
// ReferenceError: x is not defined

/**
 *  scpope & closure & hoisting (var/function)
 *  
 * 1. scpope : the global var can be access in any place(the whole file scope), local var only can be accessed by the local scope(function/block scope)!
 * Note: if a local variable not using var keywords in a function, it will become a global variable!
 * 
 * 2. closure : a function inner the other function, which can access local scope(parent function) & global scope, howerver it's vars can't be accessed by others! unless, your return it as return value!
 * 
 * 3. hoisting : move all declare/undeclare vars/function to the scope top, than assign the value or null!
 * Note: it just move the declare, not move the value!
 * 
 */

ES6 let, constkein Heben vorhanden

(() => {
  const log = console.log;
  log(a)
  // Error: Uncaught ReferenceError: Cannot access 'a' before initialization
  let a = 1;
})();


(() => {
  const log = console.log;
  log(b)
  // Error: Uncaught ReferenceError: Cannot access 'b' before initialization
  const b = 1;
})();

refs

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.