2013-03-09 8 views
74

mi sono imbattuto in 'sollevamento' JavaScript e non ho capire come questo frammento di codice realmente funzioni:JavaScript 'sollevamento'

var a = 1; 

function b() { 
    a = 10; 
    return; 

    function a() {} 
} 

b(); 
alert(a); 

so che dichiarazione di funzione simile (function a() {}) sta per essere issato all'inizio della funzione scope b ma non dovrebbe sovrascrivere il valore di a (perché le dichiarazioni di funzione sovrascrivono le dichiarazioni di variabili ma non l'inizializzazione di variabili) quindi mi aspettavo che il valore dell'avviso fosse 10 anziché 1 !!

+0

sollevamento è il comportamento predefinito di JavaScript del movimento dichiarazioni verso l'alto. * (le dichiarazioni di funzione vengono "spostate" da dove appaiono nel flusso del codice all'inizio del codice. Questo dà origine al nome "Hoisting".) * [Ulteriori informazioni] (https://github.com/) getify/You-Dont-Know-JS/blob/master/scope% 20% 26% 20closures/ch4.md) – M98

risposta

105
  1. Il mondiale a è impostato su 1
  2. b() è chiamato
  3. function a() {} viene issata e crea un locale variabile a che maschera il globale a
  4. Il locale a è impostato su 10 (sovrascrivendo la funzione a)
  5. Il globale a (sempre 1) viene avvisato
+2

grazie @Quentin Mi mancava il fatto numero 3 (quella funzione a() {} crea una variabile locale a maschere il globale a) – morfioce

+0

@Quentin: puoi mostrare con il codice come la funzione apparirebbe con il sollevamento? – SharpCoder

+0

@Brown_Dynamite - Sembra che appaia nella domanda. Funziona nell'ordine descritto in questa risposta. – Quentin

6

È perché l'ordine di compilazione/interpretazione in questo esempio è in qualche modo fuorviante. La riga function a() {} viene interpretata prima dell'esecuzione del resto della funzione, quindi all'inizio della funzione, a ha il valore . Quando si riassegna a 10, si riassegna il valore di a nell'ambito locale della funzione b(), che viene quindi scartato una volta che si torna, lasciando il valore originale di a = 1 nell'ambito globale.

È possibile verificare questo inserendo alert() s o simili nei luoghi appropriati per vedere quale è il valore di a in vari punti.

5

(1) JavaScript non ha scope block statement; piuttosto, sarà locale al codice in cui risiede il blocco.

(2) dichiarazione di variabili in funzione di un ambito, il che significa che variabili dichiarate in una funzione di Javascript sono disponibili ovunque in quella funzione, anche prima di essere assegnato un valore.

(3) All'interno del corpo di una funzione, una variabile locale ha la precedenza su una variabile globale con lo stesso nome. Se si dichiara una variabile locale o un parametro di funzione con lo stesso nome di una variabile globale, è possibile nascondere nella variabile globale.

si codice è lo stesso: (leggi il commento)

<script> 
var a = 1;   //global a = 1 
function b() { 
    a = 10;   
    var a = 20;  //local a = 20 
} 
b(); 
alert(a);   //global a = 1 
</script> 

di riferimento:
(1) JavaScript Variable Scope:
(2) A Dangerous Example of Javascript Hoisting
(3) Variable scope

Così nel tuo codice:

var a = 1;   //global a = 1 
function b() { 
    a = 10;   
    return; 
    function a() {} //local 
} 
b(); 
alert(a);   //global a = 1 
+0

in cui hai scritto "locale a non definito", che in realtà non è vero. le dichiarazioni delle funzioni vengono analizzate prima di qualsiasi contenuto dell'ambito principale, quindi in questo caso quando assegni a = 10, stai già eseguendo l'override della funzione a() {} con il valore 10. Vedere la risposta di Quentin – rochal

+0

@rochal No, leggi questo articolo [ Il sollevamento di Javascript può essere particolarmente nefasto nei loop] (http://thecomputersarewinning.com/post/a-dangerous-example-of-javascript-hoisting/) Controlla anche il codice nel browser safari ... fammi sapere E sì è un = 10' sulla maggior parte del browser .. Atteggiamento non definito non ERRORE –

+0

leggere il punto 4. dalla risposta di Quentin. A questo punto 'a' esiste già - è una funzione, non un non definito. In che modo Safari sarebbe diverso da Chrome? – rochal

0

Quando ho letto lo stesso articolo che hai fatto JavaScript Scoping and Hoisting, ero confuso anche perché l'autore non ha mai mostrato quali sono i due codici di esempio di apertura interpretati come nel compilatore.

Ecco ad esempio che hai fornito, e la seconda a pagina:

var a = 1; 
function b() { 
    function a() {} // declares 'a' as a function, which is always local 
    a = 10; 
    return; 
} 
b(); 
alert(a); 

e qui è il primo esempio nella pagina:

var foo = 1; 
function bar() { 
    var foo; // a new local 'foo' variable 
    if (!foo) { 
     foo = 10; 
    } 
    alert(foo); 
} 
bar(); 

Spero che questo aiuti

2
  1. la dichiarazione di funzione function a(){} viene issata per prima, quindi in ambito locale viene creato a.
  2. Se si hanno due variabili con lo stesso nome (una globale in un'altra in locale), la variabile locale ha sempre la precedenza sulla variabile globale.
  3. Quando si imposta a=10, si imposta la variabile locale a, non quella globale.

Quindi, il valore della variabile globale rimane lo stesso e si ottiene, allertato 1