Scope e funzioni di Javascript

Ho appena letto un grande articolo su JavaScript Scoping e Hoisting di Ben Cherry in cui dà il seguente esempio:

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

Utilizzando il codice sopra, il browser avviserà “1”.

Non sono ancora sicuro del motivo per cui restituisce “1”. Alcune delle cose che dice vengono in mente come: Tutte le dichiarazioni di funzioni sono issate in alto. È ansible applicare un ambito a una variabile utilizzando la funzione. Ancora non fa clic per me.

Il sollevamento delle funzioni significa che le funzioni vengono spostate nella parte superiore del loro ambito. Questo è,

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

sarà riscritto dall’interpeter a questo

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

Strano, eh?

Inoltre, in questo caso,

 function a() {} 

si comportava allo stesso modo di

 var a = function () {}; 

Quindi, in sostanza, questo è ciò che sta facendo il codice:

 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" 

Quello che devi ricordare è che analizza l’intera funzione e risolve tutte le dichiarazioni delle variabili prima di eseguirla. Così….

 function a() {} 

diventa davvero

 var a = function () {} 

var a forza in un ambito locale, e l’ambito variabile è attraverso l’intera funzione, quindi la variabile globale è ancora 1 perché è stata dichiarata in un ambito locale rendendola una funzione.

La funzione a è issata all’interno della funzione b :

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

che è quasi come usare var :

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

La funzione è dichiarata localmente e l’impostazione avviene solo nell’ambito locale, non nella variabile globale.

  1. funzione di dichiarazione di function a(){} viene issato per primo e si comporta come var a = function () {}; , quindi in ambito locale a viene creato.
  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, avvisato 1

function a() { } è un’istruzione di funzione, che crea a variabile locale alla funzione b .
Le variabili vengono create quando viene analizzata una funzione, indipendentemente dal fatto che l’istruzione var o function venga eseguita.

a = 10 imposta questa variabile locale.

scpope e chiusura e sollevamento (var / funzione)

  1. scpope: la var globale può essere accessibile in qualsiasi posto (l’intero scope del file), solo alla var locale è ansible accedere dall’ambito locale (scope funzione / blocco)!
    Nota: se una variabile locale non utilizza le parole chiave var in una funzione, diventerà una variabile globale!
  2. chiusura: una funzione interna all’altra funzione, che può accedere all’ambito locale (funzione genitore) e ambito globale, in che modo è imansible accedere a vars da altri! a meno che tu non lo restituisca come valore di ritorno!
  3. sollevamento: sposta tutte le azioni declare / undeclare vars / function in alto, anziché assegnare il valore o null!
    Nota: basta spostare la dichiarazione, non spostare il valore!
 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 

Sollevare è un concetto fatto per noi per renderlo più facile da capire. Quello che succede in realtà è che le dichiarazioni vengono fatte prima rispetto ai loro scopi e gli incarichi succederanno dopo (non contemporaneamente).

Quando si verificano le dichiarazioni, var a , quindi function b e all’interno di b scope, viene dichiarata la function a .

Questa funzione a ombreggia la variabile che proviene dall’ambito globale.

Dopo che le dichiarazioni sono state fatte, i valori assegnati inizieranno, il globale a otterrà il valore 1 e la function b interna function b avrà 10 . quando fai l’ alert(a) , chiamerà la variabile di ambito globale effettiva. Questo piccolo cambiamento al codice lo renderà più chiaro

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

Sta accadendo perché il nome della variabile è uguale al nome della funzione significa “a”. Pertanto, a causa dell’innalzamento di Javascript, tenta di risolvere il conflitto di denominazione e restituirà a = 1.

Sono stato anche confuso su questo fino a quando ho letto questo post su “JavaScript Hoisting” http://www.ufthelp.com/2014/11/JavaScript-Hoisting.html

Spero che sia d’aiuto.

Ecco il mio riepilogo della risposta con più annotazioni e un violino di accompagnamento con cui giocare.

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

Qual è il nocciolo della contesa in questo piccolo frammento di codice?

Caso 1:

Includere la function a(){} definizione all’interno del corpo della function b come segue. logs value of a = 1

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

Caso 2

Escludi la function a(){} definizione all’interno del corpo della function b come segue. 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 

L’osservazione ti aiuterà a capire che la dichiarazione console.log(a) registra i seguenti valori.

Caso 1: a = 1

Caso 2: a = 10

postula

  1. var a è stato definito e dichiarato in modo lessicale nell’ambito globale.
  2. a=10 Questa istruzione riassegna il valore a 10, si posiziona lessicamente all’interno della funzione b.

Spiegazione di entrambi i casi

A causa della function definition with name property della function definition with name property a è uguale alla variable a . La variable a all’interno del function body b della function body b diventa una variabile locale. La riga precedente implica che il valore globale di a rimane intatto e il valore locale di a viene aggiornato a 10.

Quindi, quello che intendiamo dire è che il codice qui sotto

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

Viene interpretato dall’interprete JS come segue.

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

Tuttavia, quando rimuoviamo la function a(){} definition , il value of 'a' dichiarato e definito al di fuori della funzione b, quel valore viene sovrascritto e diventa 10 nel caso 2. Il valore viene sovrascritto perché a=10 riferisce alla dichiarazione globale e se dovesse essere dichiarata localmente dobbiamo aver scritto 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 

Possiamo chiarire ulteriormente il nostro dubbio modificando la name property nella function a(){} definition con un nome diverso da '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 

Sollevamento In JavaScript significa che le dichiarazioni variabili vengono eseguite attraverso il programma prima che venga eseguito qualsiasi codice. Pertanto dichiarare una variabile ovunque nel codice equivale a dichiararla all’inizio.

Tutto dipende dall’ambito della variabile ‘a’. Lasciami spiegare creando ambiti come immagini.

Qui JavaScript creerà 3 ambiti.

i) Ambito globale. ii) Ambito di funzione b (). iii) Funzione a () ambito.

inserisci la descrizione dell'immagine qui

È chiaro che quando si chiama l’ambito del metodo “alert” appartiene a Global quella volta, quindi sceglierà il valore della variabile “a” solo da Global scope che è 1.

Post lungo!

Ma cancellerà l’aria!

Il modo in cui Java Script funziona è che implica un processo in due fasi:

  1. Compilazione (per modo di dire) – Questo passo registra variabili e dichiarazioni di funzioni e il loro rispettivo ambito. Non implica la valutazione dell’espressione di funzione: var a = function(){} o espressione di variabili (come l’assegnazione di 3 a x in caso di var x =3; che non è altro che la valutazione della parte RHS).

  2. Interprete: questa è la parte di esecuzione / valutazione.

Controlla l’output del codice seguente per ottenere una comprensione:

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

Il sollevamento è un concetto comportamentale di JavaScript. Sollevare (diciamo in movimento) è un concetto che spiega come e dove devono essere dichiarate le variabili.

In JavaScript, una variabile può essere dichiarata dopo che è stata utilizzata perché le dichiarazioni di funzione e le dichiarazioni di variabile vengono sempre spostate (“sollevate”) in modo invisibile nella parte superiore del loro ambito di contenimento dall’interprete JavaScript.

Nella maggior parte dei casi incontriamo due tipi di sollevamento.

1. Dichiarazione di sollevamento variabile

Lo capisco da questo pezzo di codice.

  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 

Qui la dichiarazione della variabile a sarà ospitata in alto in modo invisibile dall’interprete javascript al momento della compilazione. Quindi siamo stati in grado di ottenere valore di a. Ma questo approccio alla dichiarazione delle variabili non è raccomandato in quanto dovremmo dichiarare le variabili in cima già così.

  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 

considera un altro esempio.

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

è in realtà interpretato in questo modo:

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

In questo caso, x sarà indefinito

Non importa se il codice è stato eseguito che contiene la dichiarazione della variabile. Considera questo esempio.

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

Questa funzione risulta essere così.

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

Nella dichiarazione variabile solo i paranchi a definizione variabile, non l’assegnazione.

  1. Dichiarazione di sollevamento delle funzioni

A differenza del sollevamento variabile, anche il corpo della funzione o il valore assegnato saranno sollevati. Considera questo codice

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

Ora come abbiamo capito sia la variabile che la funzione di sollevamento, capiamo questo codice ora.

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

Questo codice risulterà essere così.

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

La funzione a () avrà scope locale all’interno di b (). a () verrà spostato in alto mentre interpreta il codice con la sua definizione (solo in caso di funzione di sollevamento), quindi a ora avrà scope locale e quindi non influenzerà lo scope globale di un certo tempo avendo il proprio scope all’interno della funzione b () .