verwirrt über Funktionsdeklaration in {}

18

var a;
if (true) {
  a = 5;

  function a() {}
  a = 0;
  console.log(a)
}
console.log(a)

Ich habe den obigen Code gesehen, eine Funktion ist in {} deklariert. Ich denke, es würde 0 0 drucken, aber es druckt 0 5

Marcus Lee
quelle
1
Im strengen Modus wird protokolliert 0 undefined.
Bestimmte Leistung
@certainPerformance gut, das ist erklärbar, aber ich kann nicht erklären, dass a = 5der Block verlässt. Laut Bergi function awird der Betrogene gehisst.
Jonas Wilms
2
Es scheint, als würde die Blockvariable mit lokalem Gültigkeitsbereich beim Erreichen der Funktionsdeklaration in den äußeren Block kopiert.
Jonas Wilms

Antworten:

13

Folgendes passiert:

(1) Es gibt zwei Variablendeklarationen a, eine innerhalb des Blocks und eine außerhalb des Blocks.

(2) Die Funktionsdeklaration wird angehoben und an die Variable der inneren Blöcke gebunden.

(3) a = 5erreicht ist, wodurch die Blockvariable überschrieben wird.

(4) Die Funktionsdeklaration wird erreicht und die Blockvariable wird in die äußere Variable kopiert. Beide sind jetzt 5.

(5) a = 0erreicht ist, wodurch die Blockvariable überschrieben wird. Die äußere Variable ist davon nicht betroffen.

 var a¹;
 if (true) {
   function a²() {} // hoisted
   a² = 5;
   a¹ = a²; // at the location of the declaration, the variable leaves the block      
   a² = 0;
  console.log(a²)
}
console.log(a¹);

Dies ist eigentlich nicht wirklich Teil der Spezifikation, sondern Teil der Semantik der Web-Legacy-Kompatibilität. Deklarieren Sie also keine Funktionen innerhalb von Blöcken und verlassen Sie sich nicht auf diesen Code, um sich auf diese Weise zu verhalten .

Dies wird auch hier erklärt

Jonas Wilms
quelle
Aber warum wird die Blockvariable nach Erreichen der Funktionsdeklaration in die äußere Variable kopiert?
Chor
@Chor nein, die Spezifikation sagt es. Ich habe keine Idee warum.
Jonas Wilms