Was bedeutet es, dass der globale Namespace verschmutzt wäre?

92

Was bedeutet es, dass der globale Namespace verschmutzt wäre?

Ich verstehe nicht wirklich, was es bedeutet, wenn ein globaler Namespace verschmutzt wird.

theJava
quelle
1
Linking für zukünftige Referenz: JavaScript Namespace Declaration
blong

Antworten:

123

Kurzer Hinweis zur Speicherbereinigung

Wenn Variablen an Umfang verlieren, können sie Speicherbereinigungen durchführen. Wenn sie einen globalen Gültigkeitsbereich haben, können sie erst erfasst werden, wenn der globale Namespace den Gültigkeitsbereich verliert.

Hier ist ein Beispiel:

var arra = [];
for (var i = 0; i < 2003000; i++) {
 arra.push(i * i + i);
}

Wenn Sie dies zu Ihrem globalen Namespace hinzufügen (zumindest für mich), sollten 10.000 KB Speicher (Win7 Firefox) hinzugefügt werden, die nicht erfasst werden. Andere Browser behandeln dies möglicherweise anders.

Während derselbe Code in einem Bereich vorhanden ist, der außerhalb des Bereichs wie folgt liegt:

(function(){
 var arra = [];
 for (var i = 0; i < 2003000; i++) {
  arra.push(i * i + i);
 }
})();

Ermöglicht es arra, den Umfang zu verlieren, nachdem die Schließung ausgeführt wurde, und für die Speicherbereinigung berechtigt zu sein.

Globaler Namespace ist dein Freund

Trotz der vielen Behauptungen gegen die Verwendung des globalen Namespace ist es Ihr Freund. Und wie ein guter Freund sollten Sie Ihre Beziehung nicht missbrauchen.

Sei sanft

Missbrauche den globalen Namespace nicht (normalerweise als "Verschmutzung" bezeichnet). Und was ich damit meine, den globalen Namespace nicht zu missbrauchen, ist - nicht mehrere globale Variablen erstellen. Hier ist ein schlechtes Beispiel für die Verwendung des globalen Namespace.

var x1 = 5;
var x2 = 20;
var y1 = 3
var y2 = 16;

var rise = y2 - y1;
var run = x2 - x1;

var slope = rise / run;

var risesquared = rise * rise;
var runsquared = run * run;

var distancesquared = risesquared + runsquared;

var distance = Math.sqrt(dinstancesquared);

Dadurch werden 11 globale Variablen erstellt, die möglicherweise irgendwo überschrieben oder falsch interpretiert werden könnten.

Seien Sie einfallsreich

Ein einfallsreicher Ansatz, der den globalen Namespace nicht verschmutzt, besteht darin, dies alles in das Modulmuster einzuschließen und nur eine globale Variable zu verwenden, während mehrere Variablen verfügbar gemacht werden.

Hier ein Beispiel: (Bitte beachten Sie, dass dies einfach ist und keine Fehlerbehandlung erfolgt.)

//Calculate is the only exposed global variable
var Calculate = function () {
 //all defintions in this closure are local, and will not be exposed to the global namespace
 var Coordinates = [];//array for coordinates
 var Coordinate = function (xcoord, ycoord) {//definition for type Coordinate
   this.x = xcoord;//assign values similar to a constructor
   this.y = ycoord;
  };

  return {//these methods will be exposed through the Calculate object
   AddCoordinate: function (x, y) {
   Coordinates.push(new Coordinate(x, y));//Add a new coordinate
  },

  Slope: function () {//Calculates slope and returns the value
   var c1 = Coordinates[0];
   var c2 = Coordinates[1];
   return c2.y - c1.y / c2.x - c1.x;//calculates rise over run and returns result
  },

  Distance: function () {
   //even with an excessive amount of variables declared, these are all still local
   var c1 = Coordinates[0];
   var c2 = Coordinates[1];

   var rise = c2.y - c1.y;
   var run = c2.x - c1.x;

   var risesquared = rise * rise;
   var runsquared = run * run;

   var distancesquared = risesquared + runsquared;

   var distance = Math.sqrt(distancesquared);

   return distance;
  }
 };
};

//this is a "self executing closure" and is used because these variables will be
//scoped to the function, and will not be available globally nor will they collide
//with any variable names in the global namespace
(function () {
 var calc = Calculate();
 calc.AddCoordinate(5, 20);
 calc.AddCoordinate(3, 16);
 console.log(calc.Slope());
 console.log(calc.Distance());
})();
Travis J.
quelle
9
Wenn Sie die Variablen in einem Verschluss behalten, wird sichergestellt, dass sie durch Müll gesammelt werden.
theJava
2
Sehr interessante Antwort, können Sie uns erklären, was der Unterschied zwischen der Verwendung einer Rendite wie in Ihrem Geltungsbereich und der Verwendung beispielsweise Calculate.prototype.Slope()außerhalb des Geltungsbereichs ist? Es wäre sehr perfekt, ein anderes Konzept zu verstehen, das dieser Problematik nahe kommt!
Ludo
Danke für diese gute Erklärung. Kurze Frage: Was möchten Sie über die Fehlerbehandlung in diesem Snippet sehen?
Sentenza
@Sentenza - Es hängt davon ab, was passieren würde, wenn später ein Fehler auftreten würde. Wenn nichts, dann braucht es wirklich keine Fehlerbehandlung. Wenn es wichtig ist, werden möglicherweise einige Tests durchgeführt, um sicherzustellen, dass keine Division durch 0 erfolgt, und eine Meldung oder Antwort, die auf einen fehlgeschlagenen Versuch hinweist (manchmal bedeutet dies nur, dass dies stillschweigend fehlschlägt). Vielleicht einige Tests, um sicherzustellen, dass Zahlen tatsächlich Zahlen und kein Text sind. Insgesamt hängt die Fehlerbehandlung jedoch auch davon ab, wer den Code verwendet. Wenn es nur Sie sind, werden Sie wahrscheinlich wissen, dass Sie bestimmte brechende Argumente nicht weitergeben müssen. Dies ist auch ein ziemlich einfaches Beispiel :)
Travis J
20

In JavaScript liegen Deklarationen außerhalb einer Funktion im globalen Bereich. Betrachten Sie dieses kleine Beispiel:

var x = 10;
function example() {
    console.log(x);
}
example(); //Will print 10

Im obigen Beispiel xwird im globalen Bereich deklariert. Jeder untergeordnete Bereich, wie der von der exampleFunktion erstellte, erbt effektiv Dinge, die in einem übergeordneten Bereich deklariert sind (in diesem Fall ist dies nur der globale Bereich).

Jeder untergeordnete Bereich, der eine im globalen Bereich deklarierte Variable erneut deklariert, wird die globale Variable beschatten und möglicherweise unerwünschte, schwer zu verfolgende Fehler verursachen:

var x = 10;
function example() {
    var x = 20;
    console.log(x); //Prints 20
}
example();
console.log(x); //Prints 10

Globale Variablen werden normalerweise nicht empfohlen, da solche Probleme auftreten können. Wenn wir die varAnweisung nicht innerhalb der exampleFunktion verwendet hätten, hätten wir versehentlich den Wert von xim globalen Bereich überschrieben :

var x = 10;
function example() {
    x = 20; //Oops, no var statement
    console.log(x); //Prints 20
}
example();
console.log(x); //Prints 20... oh dear

Wenn Sie mehr lesen und richtig verstehen möchten, empfehle ich Ihnen, die ECMAScript-Spezifikation durchzugehen . Es ist vielleicht nicht die aufregendste Lektüre, aber es wird kein Ende haben.

James Allardice
quelle
8

Wenn Sie globale Variablen, Funktionen usw. deklarieren, werden diese in den globalen Namespace verschoben. Abgesehen von Leistungs- / Speicherproblemen (die auftreten können) kann es zu unglücklichen Namenskonflikten kommen, wenn Sie eine wichtige Variable neu definieren oder nicht den Wert verwenden, von dem Sie glauben, dass Sie ihn verwenden.

Das Definieren von Dingen im globalen Namespace ist zu vermeiden.

Sergio Tulentsev
quelle
1
Eine Möglichkeit, die Definition von Dingen im globalen Namespace zu vermeiden, besteht darin, lokale Variablen zu verwenden (deklariert mit "var" innerhalb einer Funktion), aber dann ist die Variable ... lokal für die Funktion. Dies sollte so weit wie möglich geschehen.
Stéphane Glondu