Domanda Qual è lo scopo delle variabili in JavaScript?


Qual è lo scopo delle variabili in javascript? Hanno lo stesso scopo all'interno piuttosto che all'esterno di una funzione? O importa anche? Inoltre, dove sono memorizzate le variabili se sono definite globalmente?


1711
2018-02-01 08:27


origine


risposte:


Penso che il meglio che posso fare sia darti un sacco di esempi da studiare. I programmatori di Javascript sono praticamente classificati in base alla loro comprensione dell'ambito. A volte può essere abbastanza contro-intuitivo.

  1. Una variabile con ambito globale

    // global scope
    var a = 1;
    
    function one() {
      alert(a); // alerts '1'
    }
    
  2. Ambito locale

    // global scope
    var a = 1;
    
    function two(a) {
      // 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. Intermedio: Non esiste spazio per i blocchi in JavaScript (ES5; ES6 introduce let)

    un.

    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. Intermedio: Proprietà dell'oggetto

    var a = 1;
    
    function Five() {
      this.a = 5;
    }
    
    alert(new Five().a); // alerts '5'
    
  5. Avanzate: Chiusura

    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. Avanzate: Risoluzione dell'ambito basata su prototipo

    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. Globale + locale: Un caso particolarmente complesso

    var x = 5;
    
    (function () {
        console.log(x);
        var x = 10;
        console.log(x); 
    })();
    

    Questo verrà stampato undefined e 10 piuttosto che 5 e 10 poiché JavaScript sposta sempre le dichiarazioni variabili (non le inizializzazioni) nella parte superiore dell'ambito, rendendo il codice equivalente a:

    var x = 5;
    
    (function () {
        var x;
        console.log(x);
        x = 10;
        console.log(x); 
    })();
    
  8. Variabile con scope della clausola catch

    var e = 5;
    console.log(e);
    try {
        throw 6;
    } catch (e) {
        console.log(e);
    }
    console.log(e);
    

    Questo verrà stampato 5, 6, 5. All'interno della clausola di cattura e ombre globali e variabili locali. Ma questo ambito speciale è solo per la variabile catturata. Se scrivi var f; all'interno della clausola catch, quindi è esattamente come se lo aveste definito prima o dopo il blocco try-catch.


2262
2018-02-01 08:58



Javascript utilizza le catene di ambito per stabilire l'ambito di una determinata funzione. In genere esiste un ambito globale e ogni funzione definita ha il proprio ambito nidificato. Qualsiasi funzione definita all'interno di un'altra funzione ha un ambito locale che è collegato alla funzione esterna. È sempre la posizione nella sorgente che definisce l'ambito.

Un elemento nella catena dell'ambito è fondamentalmente una mappa con un puntatore all'ambito principale.

Quando si risolve una variabile, javascript inizia dall'ambito più interno e ricerca all'esterno.


219
2018-02-01 08:35



Le variabili dichiarate globalmente hanno un ambito globale. Le variabili dichiarate all'interno di una funzione hanno lo scopo di tale funzione e le variabili globali shadow con lo stesso nome.

(Sono sicuro che ci sono molte sottigliezze che i veri programmatori JavaScript saranno in grado di evidenziare in altre risposte. questa pagina su cosa esattamente this significa in qualsiasi momento. Fiduciosamente questo più link introduttivo è abbastanza per iniziare comunque.)


93
2018-02-01 08:31



JavaScript della vecchia scuola

Tradizionalmente, JavaScript ha solo due tipi di scope:

  1. Ambito globale : Le variabili sono note in tutta l'applicazione, dall'inizio dell'applicazione (*)
  2. Ambito funzionale : Le variabili sono conosciute all'interno la funzione sono dichiarati in, dall'inizio della funzione (*)

Non lo spiegherò, poiché ci sono già molte altre risposte che spiegano la differenza.


JavaScript moderno

Il le specifiche JavaScript più recenti ora concedi anche un terzo ambito:

  1. Block Scope : Le variabili sono conosciute all'interno il bloccosono dichiarati in, dal momento in cui sono dichiarati in poi (**)

Come posso creare variabili per scope di blocco?

Tradizionalmente, crei le tue variabili in questo modo:

var myVariable = "Some text";

Le variabili degli scope di blocco sono create in questo modo:

let myVariable = "Some text";

Quindi qual è la differenza tra ambito funzionale e ambito del blocco?

Per comprendere la differenza tra ambito funzionale e ambito del blocco, prendere in considerazione il seguente codice:

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

Qui, possiamo vedere che la nostra variabile j è noto solo nel primo ciclo for, ma non prima e dopo. Eppure, la nostra variabile i è noto nell'intera funzione.

Inoltre, considera che le variabili con scope a blocchi non sono note prima di essere dichiarate perché non vengono issate. Inoltre, non è consentito ridichiarare la stessa variabile nell'ambito dello stesso blocco. Questo rende le variabili con scope limitato meno soggette a errori rispetto a variabili globalmente o funzionalmente con scope, che vengono issate e che non producono errori nel caso di più dichiarazioni.


È sicuro utilizzare le variabili degli scope di blocco oggi?

Indipendentemente dal fatto che sia sicuro o meno oggi, dipende dal tuo ambiente:

  • Se stai scrivendo codice JavaScript lato server (Node.js), puoi tranquillamente usare il let dichiarazione.

  • Se stai scrivendo codice JavaScript lato client e usi un transpiler (come traceur), puoi tranquillamente usare il let affermazione, tuttavia il tuo codice è probabilmente tutt'altro che ottimale per quanto riguarda le prestazioni.

  • Se stai scrivendo codice JavaScript lato client e non usi un transpiler, devi considerare il supporto del browser.

    Oggi, 23 febbraio 2016, questi sono alcuni browser che non supportano let o avere solo supporto parziale:

    • Internet Explorer 10 e sotto (nessun supporto)
    • Firefox 43 e sotto (nessun supporto)
    • Safari 9 e sotto (nessun supporto)
    • Opera Mini 8 e sotto (nessun supporto)
    • Browser Android 4 e sotto (nessun supporto)
    • Opera 36 e sotto (supporto parziale)
    • Chome 51 e sotto (supporto parziale)

enter image description here


Come tenere traccia del supporto del browser

Per una panoramica aggiornata di quali browser supportano il let dichiarazione al momento della tua lettura di questa risposta, vedi Questo Can I Use pagina.


(*) Le variabili a livello globale e funzionale possono essere inizializzate e utilizzate prima che vengano dichiarate perché le variabili JavaScript sono issato. Ciò significa che le dichiarazioni sono sempre molto al top dello scopo.

(**) Le variabili con scope bloccate non vengono issate


55
2018-02-23 18:51



Ecco un esempio:

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

Dovrai indagare sulle chiusure e su come usarle per fare membri privati.


35
2018-02-01 08:48



La chiave, a quanto ho capito, è che Javascript ha lo scopeing a livello di funzione rispetto allo scoping di blocchi C più comune.

Ecco un buon articolo sull'argomento.


28
2018-05-15 17:38



In "Javascript 1.7" (estensione di Mozilla in Javascript) è possibile dichiarare anche variabili con scope let dichiarazione:

 var a = 4;
 let (a = 3) {
   alert(a); // 3
 }
 alert(a);   // 4

23
2018-04-06 11:19