Ho sentito che le variabili globali sono cattive, quale soluzione alternativa dovrei usare?

Ho letto dappertutto che le variabili globali sono cattive e le alternative dovrebbero essere usate. In Javascript, in particolare, quale soluzione dovrei scegliere.

Sto pensando ad una funzione, che quando alimenta due argomenti ( function globalVariables(Variable,Value) ) controlla se Variable esiste in un array locale e se imposta il suo valore su Value , altrimenti, Variable and Value viene aggiunto. Se la funzione viene chiamata senza argomenti ( function globalVariables() ) restituisce l’array. Forse se la funzione viene function globalVariables(Variable) con un solo argomento ( function globalVariables(Variable) ) restituisce il valore di Variable nella matrice.

Cosa ne pensi? Mi piacerebbe sentire le vostre soluzioni alternative e argomenti per l’utilizzo di variabili globali.

Come globalVariables();

 function append(){ globalVariables("variable1","value1"); //globalVariables() would append variable1 to it's local array. }; function retrieve(){ var localVariable1 = globalVariables("variable1"); //globalVariables() would return "value1". }; function retrieveAll(){ var localVariable1 = globalVariables(); //globalVariables() would return the globalVariable()'s entire, local [persistently stored between calls] array. }; function set(){ globalVariables("variable1","value2"); //globalVariables() would set variable1 to "value2". }; 

Si tratta di un modello Singleton BTW?

In questo specifico scenario una funzione può impostare una variabile in un punto nel tempo, e molto più tardi un’altra funzione, magari quando un utente invia un modulo, dovrà ottenere quella variabile. Pertanto la prima funzione non poteva passare la variabile come argomento alla funzione successiva in quanto non sarebbe mai stata chiamata dal primo.

Grazie, apprezzo tutto il tuo aiuto!

La ragione principale per cui le variabili globali sono scoraggiate in javascript è perché, in javascript tutto il codice condivide un singolo spazio dei nomi globale, anche javascript ha implicato variabili globali, ad es. le variabili che non sono dichiarate esplicitamente in ambito locale vengono automaticamente aggiunte allo spazio dei nomi globale. Affidarsi troppo alle variabili globali può portare a collisioni tra vari script sulla stessa pagina (leggi gli articoli di Douglas Crockford ).

Un modo per ridurre le variabili globali consiste nell’utilizzare il modello del modulo YUI . L’idea di base è di avvolgere tutto il codice in una funzione che restituisce un object che contiene funzioni a cui è necessario accedere al di fuori del modulo e assegnare il valore di ritorno a una singola variabile globale.

 var FOO = (function() { var my_var = 10; //shared variable available only inside your module function bar() { // this function not available outside your module alert(my_var); // this function can access my_var } return { a_func: function() { alert(my_var); // this function can access my_var }, b_func: function() { alert(my_var); // this function can also access my_var } }; })(); 

ora per usare le funzioni nel tuo modulo altrove, usa FOO.a_func() . In questo modo per risolvere i conflitti globali nello spazio dei nomi è sufficiente modificare il nome di FOO .

Semantica, ragazzo mio. Semantica.

Inizia con uno globale: myApp = {}; Tutto dovrebbe essere in quello. L’unica eccezione sarebbe la tua libreria AJAX (ci sono alcune eccezioni estreme come lavorare con i callback JSONP).

Ci dovrebbero essere pochissime proprietà in myApp. Ti consigliamo di conservare le proprietà dell’applicazione in contenitori come config o impostazioni.

 myApp = { config:{ prop:1 }, settings:{ prop:2 }, widgets:{ List: function(props){}, Item: function(props){} } } 

Quindi potresti avere più proprietà in moduli, componenti, singleton e costruttori di classi inferiori (widget).

Questa impostazione offre l’ulteriore vantaggio di poter accedere a qualsiasi proprietà da qualsiasi altra posizione poiché è ansible ottenerla con myApp Global. Tuttavia, dovresti usare “questo” quando ansible, perché la ricerca è più veloce. E imposta semplicemente la proprietà direttamente, non preoccuparti delle cose pseudo getter / setter. Se hai davvero bisogno di un getter / setter, codificalo per quell’uso specifico.

Il motivo per cui il tuo esempio non funziona è troppo generico e sembra che tu stia cercando una scusa per lavorare nello spazio globale.

E non essere intelligente con le variabili private. Anche loro sono cattivi: http://clubajax.org/javascript-private-variables-are-evil/

Lo stato globale causa problemi in diverse aree. Uno è il riutilizzo del codice. Quando accedete ad uno stato globale significa che il componente deve essere consapevole del proprio ambiente (qualcosa al di fuori di se stesso). Dovresti evitarlo il più ansible, perché rende il componente imprevedibile.

Diciamo che ho un object che accede alla tua funzione GlobalVariables e voglio usarlo in un’altra pagina. Come faccio a sapere per definire l’object GlobalVariables o anche come definirlo? Tuttavia, se è ansible passare le informazioni in un costruttore o come argomento a una funzione, è ansible determinare facilmente ciò che è richiesto dall’object.

Inoltre, quando si accede o si modifica l’ambito globale, si rischia di compromettere altri oggetti. Questo è il motivo per cui le librerie come jquery usano solo un singolo nome sull’ambito globale (il meno ansible). Riduce la possibilità di conflitti con altre librerie. In altre parole, l’ambito globale è fuori dal tuo controllo, quindi è pericoloso.

Davvero non vuoi farlo.
Per quanto riguarda il motivo, vedere ad esempio il post più importante qui: Qual è il codice EVIL più visto in un ambiente di produzione?

Come nota a margine, si può sempre eseguire codice “globale” senza sporcare il posto con le globali:

 (function () { var notaglobal = 1; alert(notaglobal); })(); //notaglobal is not defined in this scope 

L’utilizzo di variabili globali è generalmente una ctriggers pratica, indipendentemente dalla lingua di scelta. Non sono nemmeno (facilmente) autorizzati a usare quando sono in modalità rigorosa , cosa che consiglio vivamente.

Considera questo pezzo di codice che ho trovato:

 if (typeof session != 'undefined' && !data.cart.request_status) data.input_definitions.passengers = inflate_passenger(session, data.input_definitions.passengers); 

Avevo bisogno di girarmi e chiedere a un programmatore di feluche da dove provenisse questa variabile di session , poiché non è stata trovata nessuna ricerca di codice dove era stata impostata.

Ho scoperto che un altro pacchetto della compagnia imposta la variabile globale. Il codice è come uno scherzo: se hai bisogno di spiegarlo, probabilmente non è così bello.

Soluzione alternativa che utilizza ES6:

Se su Node, usa import o require per portare le cose desiderate in ambito lessicale, non lasciare che le persone tocchino il tuo ambiente globale senza che tu lo sappia.

 import {Sesssion} from 'api-core'; const Session = require('api-core').session; 

Se sei al frontend che consegna il codice per il browser, non puoi usare l’ import meno che tu non riesca a trascrivere il tuo codice ES6 usando Babel .

Esempio di transpiling utilizzando Gulp.js:

 // $ npm install --save-dev gulp-babel babel-preset-es2015 // gulpfile.js const gulp = require('gulp'); const babel = require('gulp-babel'); gulp.task('transpile', () => { return gulp.src('src/app.js') .pipe(babel({presets: ['es2015']})) .pipe(gulp.dest('dist')); }); // $ gulp transpile 

Soluzione alternativa:

Quando si utilizzano le funzionalità ES6 non è un’opzione l’unica soluzione alternativa per l’utilizzo di un gruppo di variabili globali, ne sta utilizzando solo una e si spera:

 // scripts/app.js var MyApp = { globals: { foo: "bar", fizz: "buzz" } }; 

Il problema con la tua soluzione è che ti rende solo più difficile capire il codice mantenendo comunque tutti i lati negativi delle variabili globali. La pagina che hai linkato copre i problemi. L’unico problema che la soluzione proposta risolve davvero è l’inquinamento da spazio dei nomi ma al costo di non essere in grado di vedere quali variabili globali vengono dichiarate con la stessa facilità con cui la dichiarazione è una chiamata di funzione).

La soluzione è scrivere codice senza variabili globali. Se una funzione ha bisogno di un valore, passala come argomento.

Altre risposte più spiegano con la funzione anonima come questo articolo menziona,

Le funzioni anonime sono difficili da eseguire il debug, la manutenzione, il test o il riutilizzo.

Ecco un esempio con la funzione normale. È più facile da leggere e capire.

 /* global variable example */ var a= 3, b= 6; function fwithglobal(){ console.log(a, b); // 3 6 expected } fwithglobal(); // first call function swithglobal(){ var a=9; console.log(a, b); // not 3 6 but 9 6 } swithglobal(); // second call /* global variable alternative(function parameter) */ function altern(){ var a= 3, b= 6; // var keyword needed f_func(a,b); s_func(a,b); } function f_func(n, m){ console.log(n, m); // 3 6 expected } function s_func(n, m){ var a=9; console.log(n, m); // 3 6 expected } altern(); // only once 
 var ASHIVA_HandsOffNHS = (function() { // VARIABLES var my_var = 10; // PRIVATE FUNCTIONS function bar() { window.alert(my_var + 5); } // PUBLIC OBJECT myObject = {}; myObject['a_func'] = function() { my_var += 10; window.alert(my_var); }; myObject['b_func'] = function() { my_var = 0; window.alert(my_var); }; return myObject; })(); ASHIVA_HandsOffNHS.a_func(); ASHIVA_HandsOffNHS.b_func(); ASHIVA_HandsOffNHS.a_func(); 

Le variabili globali sono cattive … se non gestite!

I potenziali rischi delle variabili globali sono alti quanto il piacere e la produttività di avere oggetti di uso frequente pronti all’uso.

Non credo che si debba cercare un’unica alternativa. Invece, sostengo che un object incaricato di gestire tali globali e come il codice base / componente matura, li rifatta

Una cosa non menzionata nelle risposte attuali che ritengo sia fondamentale è la comprensione dei contenitori DI e IoC. Questi risolvono molti dei problemi che le persone cercano di risolvere con le variabili globali, ma coprono le preoccupazioni correlate che i normali globali non possono, come i cicli di vita degli oggetti.