somma - variabili javascript in html




Qual è lo scopo delle variabili in JavaScript? (18)

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 note all'interno della funzione in cui sono dichiarate, dall'inizio della funzione (*)

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

JavaScript moderno

Le specifiche JavaScript più recenti ora consentono anche un terzo ambito:

  1. Block Scope : le variabili sono note all'interno del blocco in cui sono dichiarate, dal momento in cui sono dichiarate 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 è nota solo nel primo ciclo for, ma non prima e dopo. Tuttavia, la nostra variabile i è nota 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 l'istruzione let .

  • Se stai scrivendo codice JavaScript sul lato client e usi un transpiler (come Traceur ), puoi tranquillamente usare l'istruzione let , 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 o hanno solo supporto parziale:

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

Come tenere traccia del supporto del browser

Per una panoramica aggiornata di quali browser supportano l'istruzione let al momento della lettura di questa risposta, vedere questa pagina Can I Use .

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

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

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?


Modern Js, ES6 +, ' const ' e ' let '

Dovresti utilizzare lo scope scope per ogni variabile che crei, proprio come la maggior parte delle altre lingue principali. var è obsoleto . Questo rende il tuo codice più sicuro e più manutenibile.

const dovrebbe essere usato per il 95% dei casi . Rende così il riferimento variabile non può cambiare. Le proprietà del nodo Array, oggetto e DOM possono cambiare e dovrebbero essere const .

dovrebbe essere usato per qualsiasi variabile che si aspetta di essere riassegnata. Questo include all'interno di un ciclo for. Se cambi mai il valore oltre l'inizializzazione, usa let .

L'ambito del blocco significa che la variabile sarà disponibile solo tra parentesi in cui è dichiarata. Questo si estende agli ambiti interni, incluse le funzioni anonime create nell'ambito del tuo ambito.


ES5 e prima:

Le variabili in Javascript erano inizialmente (pre ES6) con funzioni lessicali. Il termine lessical scope significa che è possibile vedere l'ambito delle variabili "guardando" il codice.

Ogni variabile dichiarata con la varparola chiave ha come ambito la funzione. Tuttavia, se vengono dichiarate altre funzioni all'interno di quella funzione, tali funzioni avranno accesso alle variabili delle funzioni esterne. Questo è chiamato una catena di portata . Funziona nel modo seguente:

  1. Quando una funzione cerca di risolvere un valore variabile, guarda prima al suo ambito. Questo è il corpo della funzione, cioè tutto tra parentesi graffe {} (ad eccezione delle variabili all'interno di altre funzioni che sono in questo ambito).
  2. Se non riesce a trovare la variabile all'interno del corpo della funzione , salirà alla catena e guarderà lo scope variabile nella funzione in cui è stata definita la funzione . Questo è ciò che si intende con scope lessicale, possiamo vedere nel codice dove è stata definita questa funzione e quindi determinare la catena di scope semplicemente guardando il codice.

Esempio:

// 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();

Che cosa succede quando stiamo cercando di accedere alle variabili foo, bare foobarper la console è il seguente:

  1. Cerchiamo di registrare foo sulla console, foo può essere trovato all'interno della funzione innerFuncstessa. Pertanto, il valore di foo viene risolto nella stringa innerFunc.
  2. Proviamo a registrare la barra sulla console, la barra non può essere trovata all'interno della funzione innerFuncstessa. Pertanto, abbiamo bisogno di scalare la catena di portata . Per prima cosa guardiamo nella funzione esterna in cui è innerFuncstata definita la funzione . Questa è la funzione outerFunc. Nell'ambito di ciò outerFuncpossiamo trovare la variabile bar, che contiene la stringa 'outerFunc'.
  3. foobar non può essere trovato in innerFunc. .Pertanto, abbiamo bisogno di scalare la catena dell'oscilloscopio verso l'ambito innerFunc. Inoltre non può essere trovato qui, saliamo di un altro livello allo scopo globale (cioè l'ambito più esterno). Troviamo qui la variabile foobar che contiene la stringa 'globale'. Se non fosse stata trovata la variabile dopo aver risalito la catena di scope, il motore JS avrebbe lanciato un'eccezione referenceError .

ES6 (ES 2015) e precedenti:

Si applicano ancora gli stessi concetti di scope lessicale e scopechain ES6. Tuttavia sono stati introdotti nuovi modi per dichiarare le variabili. Ci sono i seguenti:

  • let : crea una variabile con scope a blocchi
  • const : crea una variabile con scope che deve essere inizializzata e non può essere riassegnata

La più grande differenza tra vare let/ constè che varè funzione scopata mentre let/ constsono a scope. Ecco un esempio per illustrare questo:

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

Nell'esempio precedente letVar registra il valore globale perché le variabili dichiarate letsono a scope. Esse cessano di esistere al di fuori del rispettivo blocco, quindi non è possibile accedere alla variabile al di fuori del blocco if.


1) Esiste un ambito globale, un ambito di funzione e gli ambiti with e catch. Non esiste un ambito di livello "blocco" in generale per le variabili - le istruzioni with e the catch aggiungono nomi ai loro blocchi.

2) Gli ambiti sono nidificati dalle funzioni fino all'ambito globale.

3) Le proprietà vengono risolte passando attraverso la catena del prototipo. L'istruzione with porta i nomi delle proprietà degli oggetti nell'ambito lessicale definito dal blocco with.

EDIT: ECMAAScript 6 (Harmony) è stato progettato per supportare let, e so che chrome permette un flag "harmony", quindi forse lo supporta ..

Lasciate sarebbe un supporto per l'ambito a livello di blocco, ma è necessario utilizzare la parola chiave per farlo accadere.

EDIT: Sulla base del fatto che Benjamin ha sottolineato le dichiarazioni with e catch nei commenti, ho modificato il post e aggiunto altro. Sia le istruzioni with che the catch introducono le variabili nei rispettivi blocchi, e questo è un ambito di blocco. Queste variabili sono alterate alle proprietà degli oggetti passati in esse.

 //chrome (v8)

 var a = { 'test1':'test1val' }
 test1   // error not defined
 with (a) { var test1 = 'replaced' }
 test1   // undefined
 a       // a.test1 = 'replaced'

MODIFICA: Esempio di chiarimento:

test1 ha un ambito con il blocco with, ma è aliasato a a.test1. 'Var test1' crea una nuova variabile test1 nel contesto lessicale superiore (funzione o globale), a meno che non sia una proprietà di a - quale essa sia.

Yikes! Stai attento a usare 'with' - proprio come var è un noop se la variabile è già definita nella funzione, è anche un noop rispetto ai nomi importati dall'oggetto! Un po 'di testa a testa sul nome già definito lo renderebbe molto più sicuro. Io personalmente non userò mai a causa di questo.


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 creare membri privati .


Esistono ALMOST solo due tipi di ambiti JavaScript:

  • l'ambito di ciascuna dichiarazione var è associato alla funzione di chiusura più immediata
  • se non esiste alcuna funzione di inclusione per una dichiarazione var, è un ambito globale

Quindi, qualsiasi blocco diverso dalle funzioni non crea un nuovo ambito. Questo spiega perché i cicli for-over sovrascrivono le variabili con ambito esterno:

var i = 10, v = 10;
for (var i = 0; i < 5; i++) { var v = 5; }
console.log(i, v);
// output 5 5

Usando invece le funzioni:

var i = 10, v = 10;
$.each([0, 1, 2, 3, 4], function(i) { var v = 5; });
console.log(i,v);
// output 10 10

Nel primo esempio, non vi era alcun ambito di blocco, quindi le variabili inizialmente dichiarate sono state sovrascritte. Nel secondo esempio, c'era un nuovo ambito a causa della funzione, quindi le variabili inizialmente dichiarate erano SHADOWED e non sovrascritte.

Questo è quasi tutto ciò che devi sapere in termini di scope JavaScript, eccetto:

In questo modo è possibile vedere lo scope JavaScript in realtà estremamente semplice, sebbene non sempre intuitivo. Alcune cose da sapere:

  • le dichiarazioni var sono issate nella parte superiore dello scope. Ciò significa che, indipendentemente da dove avviene la dichiarazione var, il compilatore è come se la variabile venisse eseguita in alto
  • vengono combinate più dichiarazioni var all'interno dello stesso ambito

Quindi questo codice:

var i = 1;
function abc() {
  i = 2;
  var i = 3;
}
console.log(i);     // outputs 1

è equivalente a:

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

Questo può sembrare contro intuitivo, ma ha senso dal punto di vista di un designer di linguaggio imperativo.


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

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

JavaScript ha solo due tipi di ambito:

  1. Global Scope : Global non è altro che un ambito a livello di finestra. Qui, variabile presente in tutta l'applicazione.
  2. Ambito funzionale : la variabile dichiarata all'interno di una funzione con la parola chiave var ha un ambito funzionale.

Ogni volta che viene chiamata una funzione, viene creato un oggetto con scope variabile (incluso nella catena di portata) che è seguito dalle variabili in JavaScript.

        a = "global";
         function outer(){ 
              b = "local";
              console.log(a+b); //"globallocal"
         }
outer();

Catena di portata ->

  1. Livello finestra: a e a funzione outer sono al livello più alto nella catena di portata.
  2. quando la funzione esterna ha chiamato un nuovo variable scope object (e incluso nella catena di scope) aggiunto con la variabile b al suo interno.

Ora, quando una variabile a richiede, cerca dapprima l'ambito della variabile più vicino e se la variabile non è presente rispetto a quella del prossimo oggetto della variabile scope chain. Che è in questo caso il livello della finestra.


L'idea di scoping in JavaScript quando originariamente progettata da Brendan Eich proveniva dal linguaggio HyperTalk scripting HyperCard .

In questa lingua, i display erano fatti come una pila di carte indice. C'era una carta principale indicata come sfondo. Era trasparente e può essere visto come la carta in basso. Qualsiasi contenuto su questa carta base è stato condiviso con le carte posizionate sopra di esso. Ogni carta posta in cima aveva il suo contenuto che aveva la precedenza sulla carta precedente, ma aveva ancora accesso alle carte precedenti se lo si desiderava.

Questo è esattamente il modo in cui è progettato il sistema di scoping di JavaScript. Ha solo nomi diversi. Le carte in JavaScript sono conosciute come contesti di esecuzione ECMA . Ciascuno di questi contesti contiene tre parti principali. Un ambiente variabile, un ambiente lessicale e un tale legame. Tornando al riferimento delle carte, l'ambiente lessicale contiene tutto il contenuto delle carte precedenti più in basso nella pila. Il contesto attuale è in cima allo stack e qualsiasi contenuto dichiarato verrà memorizzato nell'ambiente variabile. L'ambiente variabile avrà la precedenza in caso di conflitti di denominazione.

Questo legame punterà all'oggetto contenitore. A volte gli ambiti oi contesti di esecuzione cambiano senza che l'oggetto contenitore si modifichi, ad esempio in una funzione dichiarata in cui l'oggetto contenitore può essere una window o una funzione di costruzione.

Questi contesti di esecuzione vengono creati ogni volta che viene trasferito il controllo. Il controllo viene trasferito quando il codice inizia ad essere eseguito, e questo viene fatto principalmente dall'esecuzione della funzione.

Quindi questa è la spiegazione tecnica. In pratica, è importante ricordare che in JavaScript

  • Gli ambiti sono tecnicamente "Contesti di esecuzione"
  • I contesti formano una pila di ambienti in cui sono memorizzate le variabili
  • La cima della pila ha la precedenza (il fondo è il contesto globale)
  • Ogni funzione crea un contesto di esecuzione (ma non sempre una nuova questa associazione)

Applicando questo a uno degli esempi precedenti (5. "Chiusura") in questa pagina, è possibile seguire la pila di contesti di esecuzione. In questo esempio ci sono tre contesti nello stack. Sono definiti dal contesto esterno, dal contesto nella funzione invocata immediatamente chiamata da var sei e dal contesto nella funzione restituita all'interno della funzione immediatamente invocata di var sei.

i ) Il contesto esterno. Ha un ambiente variabile di a = 1
ii ) Il contesto IIFE, ha un ambiente lessicale di a = 1, ma un ambiente variabile di a = 6 che ha la precedenza nello stack
iii ) Il contesto della funzione restituita, ha un ambiente lessicale di a = 6 e questo è il valore referenziato nell'avviso quando chiamato.



Ogni frammento di codice JavaScript (codice o funzioni globali) ha una catena di portata ad esso associata. Questa catena dell'ambito è una lista o una catena di oggetti che definisce le variabili "nell'ambito" per quel codice. Quando JavaScript deve cercare il valore di una variabile x (un processo chiamato risoluzione variabile ), inizia guardando il primo oggetto della catena. Se quell'oggetto ha una proprietà denominata x , viene utilizzato il valore di tale proprietà. Se il primo oggetto non ha una proprietà chiamata x , JavaScript continua la ricerca con l'oggetto successivo nella catena. Se il secondo oggetto non ha una proprietà chiamata x , la ricerca passa all'oggetto successivo e così via. Se x non è una proprietà di nessuno degli oggetti nella catena dell'ambito, allora x non rientra nell'ambito per quel codice e si verifica un'eccezione ReferenceError. Nel codice JavaScript di primo livello (ovvero, il codice non è contenuto in alcuna definizione di funzione), la catena dell'ambito è costituita da un singolo oggetto, l'oggetto globale. In una funzione non annidata, la catena dell'ambito è costituita da due oggetti. Il primo è l'oggetto che definisce i parametri della funzione e le variabili locali, mentre il secondo è l'oggetto globale. In una funzione nidificata, la catena di ambito ha tre o più oggetti. È importante capire come viene creata questa catena di oggetti. Quando una funzione è DEFINED , memorizza la catena di ambito allora in vigore. Quando questa funzione è INVOKED , crea un nuovo oggetto per memorizzare le sue variabili locali e aggiunge quel nuovo oggetto alla catena dell'ambito memorizzata per creare una nuova catena più lunga che rappresenta l'ambito per tale chiamata di funzione. Questo diventa più interessante per le funzioni annidate perché ogni volta che viene chiamata la funzione esterna, la funzione interna viene nuovamente definita.Poiché la catena dell'ambito differisce su ogni invocazione della funzione esterna, la funzione interna sarà sottilmente diversa ogni volta che viene definita - il codice della funzione interna sarà identico su ogni invocazione della funzione esterna, ma la catena dell'ambito associata a quella codice sarà diverso . Questa nozione di una catena di portata è fondamentale per comprendere le chiusure.


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) { // 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. Intermedio : non esiste lo scope block 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. Avanzato : 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. Avanzato : 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. Global + Local : un caso particolarmente complesso

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

    Questo verrà stampato undefined e 10 anziché 5 e 10 poiché JavaScript sposta sempre le dichiarazioni variabili (non le inizializzazioni) nella parte superiore dello scope, 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 catch, ombreggia le variabili globali e 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.


eseguire il codice. spero che questo ti dia un'idea di 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);

Esistono due tipi di ambiti in JavaScript.

  1. Scopo globale : la variabile che viene annunciata nell'ambito globale può essere utilizzata in qualsiasi parte del programma in modo agevole. Per esempio:

    var carName = " BMW";
    
    // code here can use carName
    
    function myFunction() {
         // code here can use carName 
    }
    
  2. Ambito funzionale o ambito locale : la variabile dichiarata in questo ambito può essere utilizzata solo nella sua funzione. Per esempio:

    // code here can not use carName
    function myFunction() {
       var carName = "BMW";
       // code here can use carName
    }
    

In JavaScript ci sono due tipi di scope:

  • Ambito locale
  • Ambito globale

La funzione Below ha una variabile scope locale carName. E questa variabile non è accessibile dall'esterno della funzione.

function myFunction() {
    var carName = "Volvo";
    alert(carName);
    // code here can use carName
}

La classe below ha una variabile scope globale carName. E questa variabile è accessibile da ogni parte della classe.

class {

    var carName = " Volvo";

    // code here can use carName

    function myFunction() {
        alert(carName);
        // code here can use carName 
    }
}

ECMAScript 6 ha introdotto le parole chiave let e const. Queste parole chiave possono essere utilizzate al posto della parola chiave var. Contrariamente alla parola chiave var, le parole chiave let e const supportano la dichiarazione dell'ambito locale all'interno delle istruzioni di blocco.

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

La mia comprensione è che ci sono 3 ambiti: ambito globale, disponibile a livello globale; ambito locale, disponibile per un'intera funzione indipendentemente dai blocchi; e l'ambito del blocco, disponibile solo per il blocco, istruzione o espressione su cui è stato utilizzato. L'ambito globale e locale sono indicati con la parola chiave "var", all'interno di una funzione o all'esterno, e l'ambito del blocco è indicato con la parola chiave "let".

Per coloro che credono che ci sia solo un ambito globale e locale, si prega di spiegare perché Mozilla avrebbe un'intera pagina che descriveva le sfumature dell'ambito dei blocchi in JS.

let


Prova questo curioso esempio. Nell'esempio seguente se a era un valore numerico inizializzato a 0, vedresti 0 e quindi 1. Tranne a è un oggetto e javascript passerà a f1 un puntatore di una copia piuttosto che di una copia. Il risultato è che ricevi lo stesso avviso entrambe le volte.

var a = new Date();
function f1(b)
{
    b.setDate(b.getDate()+1);
    alert(b.getDate());
}
f1(a);
alert(a.getDate());




var