Dichiarazioni di funzioni all’interno di istruzioni if ​​/ else?

Come vengono gestite le dichiarazioni di funzione?

var abc = ''; if(1 === 0){ function a(){ abc = 7; } }else if('a' === 'a'){ function a(){ abc = 19; } }else if('foo' === 'bar'){ function a(){ abc = 'foo'; } } a(); document.write(abc); //writes "foo" even though 'foo' !== 'bar' 

Questo esempio produce diversi output in Chrome e Firefox. Chrome emette foo mentre le uscite FF 19 .

Quando è stata posta questa domanda, ECMAScript 5 (ES5) era prevalente. Nella modalità strict di ES5, le dichiarazioni di funzione non possono essere nidificate all’interno di un blocco if come mostrato nella domanda. In modalità non rigorosa, i risultati erano imprevedibili. Diversi browser e motori implementavano le proprie regole per come gestivano le dichiarazioni di funzione all’interno dei blocchi.

A partire dal 2018, molti browser supportano ECMAScript 2015 (ES2015) nella misura in cui le dichiarazioni di funzione sono ora consentite all’interno dei blocchi . In un ambiente ES2015, all’interno di quel blocco verrà inclusa una dichiarazione di funzione all’interno di un blocco. Il codice nella domanda genererà un errore di funzione non definito poiché la funzione a è dichiarata solo nell’ambito di istruzioni if e quindi non esiste nell’ambito globale.

Se è necessario definire una funzione in modo condizionale, è necessario utilizzare le espressioni di funzione .

Da http://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/

In javascript, hai la dichiarazione di funzione:

 function foo() { } 

e l’espressione della funzione

 var foo = function() { } 

Citando da http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting

“Le dichiarazioni di funzione e le variabili di funzione vengono sempre spostate (” issate “) in cima al loro scope JavaScript dall’interprete JavaScript”.

Quindi, quello che è successo nel tuo primo esempio è che la dichiarazione di function a() della function a() , viene issata in cima all’ambito Javascript, producendo così “foo” anche se il valore if viene valutato come falso

Pensa a var foo come una normale istruzione Javascript, è eseguita solo sul runtime del tuo javascript, diversamente dalla function foo() , ecco perché il seguito è valido:

 alert(foo()); function foo() { return 'gw ganteng'; } 

Qui, la function foo() viene analizzata dal parser, inserendo foo() nell’attuale scope, prima di tentare di chiamare alert(foo())

http://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/

Nell’esecuzione di JavaScript c’è il contesto (che ECMA 5 irrompe in LexicalEnvironment, VariableEnvironment e ThisBinding) e Process (un insieme di istruzioni da richiamare in sequenza). Le dichiarazioni contribuiscono a VariableEnvironment quando viene immesso l’ambito di esecuzione. Sono distinti dalle dichiarazioni (come il ritorno) e non sono soggetti alle loro regole di processo.

L’ECMA-262 v5 richiede implementazioni per registrare tutte le dichiarazioni di funzioni e variabili durante il primo passaggio quando si immette qualsiasi nuovo contesto di esecuzione a livello globale o di funzione. Chrome lo sta facendo tecnicamente proprio qui perché sta guardando all’interno else e then blocca e registra a() prima dell’esecuzione. Sfortunatamente produce i risultati più illeggibili.

FF sta aspettando fino a quando non valuta l’istruzione if prima di valutare e aggiunge le dichiarazioni di funzioni e variabili al contesto corrente. BTW. Entrambi i browser fanno in questo modo all’interno delle clausole catch e finally.

Si tratta solo di due diverse implementazioni ECMA che si occupano di una funzionalità che non dovrebbe essere lì per cominciare. Lo scenario in questione mostra perché le dichiarazioni di funzione non dovrebbero essere contenute nelle istruzioni del stream di controllo.