Ich habe überall gelesen, dass globale Variablen schlecht sind und Alternativen verwendet werden sollten. Welche Lösung sollte ich speziell in Javascript wählen?
Ich denke an eine Funktion, die beim Einspeisen von zwei Argumenten ( function globalVariables(Variable,Value)
) prüft, ob Variable in einem lokalen Array vorhanden ist und ob sie ihren Wert auf Value
else setzt Variable
und Value
angehängt wird. Wenn die Funktion ohne Argumente ( function globalVariables()
) aufgerufen wird , gibt sie das Array zurück. Wenn die Funktion mit nur einem Argument ( function globalVariables(Variable)
) ausgelöst wird, gibt sie möglicherweise den Wert von Variable
im Array zurück.
Was denken Sie? Ich würde gerne Ihre alternativen Lösungen und Argumente für die Verwendung globaler Variablen hören.
Wie würden Sie verwenden 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".
};
Ist das übrigens ein Singleton-Muster ?
In diesem speziellen Szenario kann eine Funktion eine Variable zu einem bestimmten Zeitpunkt festlegen, und viel später muss eine andere Funktion, möglicherweise wenn ein Benutzer ein Formular sendet, diese Variable abrufen. Daher konnte die erste Funktion die Variable nicht als Argument an die spätere Funktion übergeben, da sie niemals von der ersten aufgerufen werden würde.
Vielen Dank, ich danke Ihnen für Ihre Hilfe!
quelle
Antworten:
Der Hauptgrund, warum globale Variablen in Javascript nicht empfohlen werden, liegt darin, dass in Javascript alle Codes einen einzigen globalen Namespace gemeinsam haben und auch Javascript globale Variablen impliziert hat, d. H. Variablen, die nicht explizit im lokalen Bereich deklariert sind, werden automatisch zum globalen Namespace hinzugefügt. Wenn Sie sich zu sehr auf globale Variablen verlassen, kann dies zu Kollisionen zwischen verschiedenen Skripten auf derselben Seite führen (lesen Sie die Artikel von Douglas Crockford ).
Eine Möglichkeit, globale Variablen zu reduzieren, besteht darin, das YUI-Modulmuster zu verwenden . Die Grundidee besteht darin, Ihren gesamten Code in eine Funktion zu verpacken, die ein Objekt zurückgibt, das Funktionen enthält, auf die außerhalb Ihres Moduls zugegriffen werden muss, und den Rückgabewert einer einzelnen globalen Variablen zuzuweisen.
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 } }; })();
Verwenden Sie jetzt, um Funktionen in Ihrem Modul an anderer Stelle zu verwenden
FOO.a_func()
. Auf diese Weise müssen Sie nur den Namen von ändern, um globale Namespace-Konflikte zu lösenFOO
.quelle
FOO().a_func()
. Ah, es macht jetzt Sinn!Semantik mein Junge. Semantik.
Beginnen Sie mit einem globalen: myApp = {}; Alles sollte darin sein. Die einzige Ausnahme wäre Ihre AJAX-Bibliothek (es gibt einige extreme Ausnahmen wie das Arbeiten mit JSONP-Rückrufen).
In myApp sollten nur sehr wenige Eigenschaften vorhanden sein. Sie möchten Ihre Anwendungseigenschaften in Containern wie config oder settings speichern.
myApp = { config:{ prop:1 }, settings:{ prop:2 }, widgets:{ List: function(props){}, Item: function(props){} } }
Dann haben Sie möglicherweise mehr Eigenschaften in niedrigeren Modulen, Komponenten, Singletons und Klassenkonstruktoren (Widgets).
Dieses Setup bietet Ihnen den zusätzlichen Vorteil, dass Sie von jedem anderen Ort aus auf jede Eigenschaft zugreifen können, da Sie sie mit myApp global abrufen können. Sie sollten jedoch "dies" verwenden, wann immer dies möglich ist, da die Suche schneller ist. Und stellen Sie die Eigenschaft einfach direkt ein, kümmern Sie sich nicht um das Pseudo-Getter / Setter-Zeug. Wenn Sie wirklich einen Getter / Setter benötigen, codieren Sie ihn für diese spezielle Verwendung.
Der Grund, warum Ihr Beispiel nicht funktioniert, ist, dass es zu allgemein ist und Sie nach einer Ausrede suchen, um im globalen Raum zu arbeiten.
Und seien Sie nicht schlau mit privaten Variablen. Sie sind auch schlecht: http://clubajax.org/javascript-private-variables-are-evil/
quelle
Der globale Staat verursacht in mehreren Bereichen Probleme. Eine davon ist die Wiederverwendung von Code. Wenn Sie auf einen globalen Status zugreifen, bedeutet dies, dass sich die Komponente ihrer Umgebung bewusst sein muss (etwas außerhalb von sich selbst). Sie sollten dies so weit wie möglich vermeiden, da dies die Komponente unvorhersehbar macht.
Angenommen, ich habe ein Objekt, das auf Ihre globalVariables-Funktion zugreift, und ich möchte es auf einer anderen Seite verwenden. Woher weiß ich, wie ich das globalVariables-Objekt definiere oder wie ich es überhaupt definiere? Wenn Sie die Informationen jedoch an einen Konstruktor oder als Argument an eine Funktion übergeben können, kann ich leicht feststellen, was für das Objekt erforderlich ist.
Auch wenn Sie auf den globalen Bereich zugreifen oder ihn ändern, besteht die Gefahr, dass andere Objekte davon betroffen sind. Aus diesem Grund verwenden Bibliotheken wie jquery im globalen Bereich nur einen einzigen Namen (den geringstmöglichen). Dies verringert die Möglichkeit von Konflikten mit anderen Bibliotheken. Mit anderen Worten, der globale Geltungsbereich liegt außerhalb Ihrer Kontrolle und ist daher gefährlich.
quelle
Das willst du wirklich nicht.
Informationen zum Grund finden Sie z. B. im oberen Beitrag: Was ist der schlechteste Code, den Sie jemals in einer Produktionsunternehmensumgebung gesehen haben?
Als Randnotiz kann man immer "globalen" Code ausführen, ohne den Ort mit Globalen zu verunreinigen:
(function () { var notaglobal = 1; alert(notaglobal); })(); //notaglobal is not defined in this scope
quelle
Die Verwendung globaler Variablen ist im Allgemeinen eine schlechte Praxis, unabhängig von der Sprache der Wahl. Sie dürfen nicht einmal (leicht) im strengen Modus verwendet werden , was ich sehr empfehlen kann.
Betrachten Sie diesen Code, den ich gefunden habe:
if (typeof session != 'undefined' && !data.cart.request_status) data.input_definitions.passengers = inflate_passenger(session, data.input_definitions.passengers);
Ich musste mich umdrehen und einen Felow-Programmierer fragen, woher diese
session
Variable stammt, da keine Codesuche angezeigt wurde, wo sie eingestellt war.Ich stellte fest, dass ein anderes Paket der Firma die globale Variable setzt. Code ist wie ein Witz: Wenn Sie es erklären müssen, ist es wahrscheinlich nicht so gut.
Problemumgehung mit ES6:
Wenn Sie bei Node das gewünschte Material verwenden
import
oderrequire
in den lexikalischen Bereich bringen, lassen Sie nicht zu, dass Personen Ihre globale Umgebung berühren, ohne dass Sie es wissen.import {Sesssion} from 'api-core'; const Session = require('api-core').session;
Wenn Sie am Frontend Code für den Browser bereitstellen, können Sie diesen nur verwenden,
import
wenn Sie Ihren ES6-Code mit Babel transpilieren .Beispiel für das Transpilieren mit 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
Legacy-Problemumgehung:
Wenn die Verwendung von ES6-Funktionen keine Option ist, besteht die einzige Problemumgehung für die Verwendung einer Reihe globaler Variablen darin, nur eine zu verwenden, und hoffen:
// scripts/app.js var MyApp = { globals: { foo: "bar", fizz: "buzz" } };
quelle
Das Problem bei Ihrer Lösung ist, dass Sie den Code nur schwerer verstehen, während Sie alle Nachteile globaler Variablen beibehalten. Die Seite, auf die Sie verlinkt haben, behandelt die Probleme. Das einzige Problem, das Ihre vorgeschlagene Lösung wirklich löst, ist die Verschmutzung des Namespaces, aber auf Kosten der Tatsache, dass Sie nicht sehen können, welche globalen Variablen so einfach deklariert werden, wie die Deklaration ein Funktionsaufruf ist.
Die Lösung besteht darin, Code ohne globale Variablen zu schreiben. Wenn eine Funktion einen Wert benötigt, übergeben Sie ihn als Argument.
quelle
Andere Antworten erklären die meisten mit anonymer Funktion, wie in diesem Artikel erwähnt,
Hier sind Beispiele mit normaler Funktion. Es ist leichter zu lesen und zu verstehen.
/* 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
quelle
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();
quelle
Globale Variablen sind schlecht ... wenn sie nicht verwaltet werden!
Das potenzielle Risiko globaler Variablen ist so hoch wie die Freude und Produktivitätssteigerung, häufig verwendete Objekte einsatzbereit zu haben.
Ich glaube nicht, dass man eine einzige Alternative suchen sollte. Stattdessen befürworte ich ein Objekt, das für die Verwaltung dieser Globals verantwortlich ist, und überarbeite sie, wenn die Codebasis / Komponente reift
Eine Sache, die in den aktuellen Antworten nicht erwähnt wird und die ich für kritisch halte, ist das Verständnis von DI- und IoC-Containern. Diese befassen sich mit vielen der Probleme, die Menschen mit globalen Variablen zu lösen versuchen, decken jedoch verwandte Probleme ab, die einfache Globale nicht können, wie z. B. Objektlebenszyklen.
quelle