Cosa significa che lo spazio dei nomi globale sarebbe inquinato?


Risposte:


124

Nota rapida sulla raccolta dei rifiuti

Poiché le variabili perdono l'ambito, saranno idonee per la garbage collection. Se hanno ambito globale, non saranno idonei per la raccolta fino a quando lo spazio dei nomi globale non perde l'ambito.

Ecco un esempio:

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

Aggiungendolo al tuo spazio dei nomi globale (almeno per me) dovresti aggiungere 10.000 kb di utilizzo della memoria (win7 firefox) che non verranno raccolti. Altri browser potrebbero gestirlo in modo diverso.

Considerando che avere lo stesso codice in uno scope che esula dall'ambito in questo modo:

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

Consentirà arradi perdere l'ambito dopo l'esecuzione della chiusura e sarà idoneo per la garbage collection.

Lo spazio dei nomi globale è tuo amico

Nonostante le molte affermazioni contro l'utilizzo dello spazio dei nomi globale, è tuo amico. E come un buon amico, non dovresti abusare della tua relazione.

Sii gentile

Non abusare (di solito indicato come "inquinante") lo spazio dei nomi globale. E quello che intendo per non abusare dello spazio dei nomi globale è: non creare più variabili globali. Ecco un cattivo esempio di utilizzo dello spazio dei nomi globale.

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

Questo creerà 11 variabili globali che potrebbero essere sovrascritte o interpretate male da qualche parte.

Sii pieno di risorse

Un approccio più intraprendente, che non inquina lo spazio dei nomi globale, sarebbe racchiudere tutto questo nel modello del modulo e utilizzare solo una variabile globale mentre espone più variabili.

Ecco un esempio: (Si prega di notare che questo è semplice e non c'è gestione degli errori)

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

10
mantenere le variabili all'interno di una chiusura garantisce che vengano raccolte in modo spazzatura.
theJava

2
Risposta molto interessante, puoi spiegarci qual è la differenza tra l'utilizzo di un ritorno come hai fatto nel tuo ambito e l'utilizzo ad esempio Calculate.prototype.Slope()al di fuori dello scopo? Sarebbe molto perfetto sottovalutare un altro concetto vicino a questa problematica!
Ludo

Grazie per questa buona spiegazione. Domanda veloce: cosa vorresti vedere sulla gestione degli errori in quello snippet?
Sentenza

@Sentenza - Dipende da cosa succederebbe se ci fosse un errore su tutta la linea. Se non altro, non necessita di gestione degli errori. Se è importante, forse alcuni test per assicurarsi che la divisione per 0 non avvenga e un messaggio o una risposta per indicare un tentativo fallito (a volte questo significa semplicemente fallire silenziosamente). Forse alcuni test per assicurarsi che i numeri siano effettivamente numeri e non testo. Nel complesso, tuttavia, la gestione degli errori dipende anche da chi utilizza il codice. Se sei solo tu, probabilmente saprai di non passare alcuni argomenti di rottura. Anche questo è un esempio piuttosto semplice :)
Travis J

20

In JavaScript, le dichiarazioni al di fuori di una funzione sono nell'ambito globale. Considera questo piccolo esempio:

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

Nell'esempio sopra, xè dichiarato nell'ambito globale. Qualsiasi ambito figlio, come quello creato dalla examplefunzione, eredita effettivamente le cose dichiarate in tutti gli ambiti padre (in questo caso, è solo l'ambito globale).

Qualsiasi ambito figlio che dichiara nuovamente una variabile dichiarata nell'ambito globale oscurerà la variabile globale, causando potenzialmente bug indesiderati e difficili da tracciare:

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

Le variabili globali di solito non sono consigliate a causa della possibilità di causare problemi come questo. Se non avessimo usato l' varistruzione all'interno della examplefunzione, avremmo accidentalmente sovrascritto il valore di xnell'ambito globale:

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

Se vuoi leggere di più e capirlo correttamente, ti suggerisco di passare attraverso la specifica ECMAScript . Potrebbe non essere la più eccitante delle letture, ma non aiuterà a finire.


8

Quando dichiari variabili globali, funzioni, ecc., Esse, ehm, vanno nello spazio dei nomi globale. A parte i problemi di prestazioni / memoria (che possono sorgere), è probabile che ti imbatti in uno sfortunato conflitto di nomi, quando ridefinirai una variabile importante o non utilizzerai il valore che pensi di utilizzare.

La definizione di cose nello spazio dei nomi globale deve essere evitata.


1
Un modo per evitare di definire le cose nello spazio dei nomi globale è usare variabili locali (dichiarate con "var" all'interno di una funzione), ma poi la variabile è ... locale alla funzione. Questo dovrebbe essere fatto il più possibile.
Stéphane Glondu
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.