Co to znaczy, że globalna przestrzeń nazw byłaby zanieczyszczona?
Naprawdę nie rozumiem, co oznacza zanieczyszczenie globalnej przestrzeni nazw.
Odpowiedzi:
Szybka uwaga na temat zbierania śmieci
Ponieważ zmienne tracą zasięg, będą kwalifikować się do czyszczenia pamięci. Jeśli mają zasięg globalny, nie będą kwalifikować się do zbierania, dopóki globalna przestrzeń nazw nie utraci zakresu.
Oto przykład:
var arra = [];
for (var i = 0; i < 2003000; i++) {
arra.push(i * i + i);
}
Dodanie tego do globalnej przestrzeni nazw (przynajmniej dla mnie) powinno zapewnić 10 000 kB wykorzystania pamięci (firefox win7), które nie zostaną zebrane. Inne przeglądarki mogą to obsługiwać inaczej.
Zważywszy, że posiadanie tego samego kodu w zakresie, który wykracza poza ten zakres:
(function(){
var arra = [];
for (var i = 0; i < 2003000; i++) {
arra.push(i * i + i);
}
})();
Pozwoli arrastracić zakres po wykonaniu zamknięcia i będzie kwalifikować się do czyszczenia pamięci.
Globalna przestrzeń nazw jest Twoim przyjacielem
Pomimo wielu zarzutów przeciwko używaniu globalnej przestrzeni nazw, jest to twój przyjaciel. I jak dobry przyjaciel, nie powinieneś nadużywać swojego związku.
Bądź delikatny
Nie nadużywaj (zwykle nazywanej „zanieczyszczeniem”) globalnej przestrzeni nazw. Nie nadużywaj globalnej przestrzeni nazw mam na myśli - nie twórz wielu zmiennych globalnych. Oto zły przykład użycia globalnej przestrzeni nazw.
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);
Stworzy to 11 zmiennych globalnych, które mogą zostać gdzieś nadpisane lub źle zinterpretowane.
Bądź zaradny
Bardziej pomysłowym podejściem, które nie zanieczyszcza globalnej przestrzeni nazw, byłoby zawinięcie tego wszystkiego we wzorzec modułu i użycie tylko jednej zmiennej globalnej podczas ujawniania wielu zmiennych.
Oto przykład: (Należy pamiętać, że jest to proste i nie ma obsługi błędów)
//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());
})();
Calculate.prototype.Slope()poza zakresem? Byłoby doskonale zrozumieć inną koncepcję bliską tej problematyce!
W JavaScript deklaracje poza funkcją znajdują się w zasięgu globalnym. Rozważ ten mały przykład:
var x = 10;
function example() {
console.log(x);
}
example(); //Will print 10
W powyższym przykładzie xjest zadeklarowana w zakresie globalnym. Każdy zakres podrzędny, taki jak ten utworzony przez examplefunkcję, skutecznie dziedziczy rzeczy zadeklarowane w dowolnych zakresach nadrzędnych (w tym przypadku jest to tylko zasięg globalny).
Każdy zakres podrzędny, który ponownie deklaruje zmienną zadeklarowaną w zakresie globalnym, będzie cieniał zmienną globalną, potencjalnie powodując niechciane, trudne do śledzenia błędy:
var x = 10;
function example() {
var x = 20;
console.log(x); //Prints 20
}
example();
console.log(x); //Prints 10
Zmienne globalne zwykle nie są zalecane, ponieważ mogą powodować tego typu problemy. Gdybyśmy nie użyli varinstrukcji wewnątrz examplefunkcji, przypadkowo nadpisalibyśmy wartość xw zakresie globalnym:
var x = 10;
function example() {
x = 20; //Oops, no var statement
console.log(x); //Prints 20
}
example();
console.log(x); //Prints 20... oh dear
Jeśli chcesz przeczytać więcej i dobrze to zrozumieć, proponuję zapoznać się ze specyfikacją ECMAScript . Może nie jest to najbardziej ekscytująca lektura, ale pomoże to bez końca.
Kiedy deklarujesz zmienne globalne, funkcje itp., One, ehm, przechodzą do globalnej przestrzeni nazw. Oprócz problemów z wydajnością / pamięcią (które mogą się pojawić), prawdopodobnie napotkasz niefortunną kolizję nazw, kiedy ponownie zdefiniujesz ważną zmienną lub nie użyjesz wartości, której myślisz, że używasz.
Należy unikać definiowania elementów w globalnej przestrzeni nazw.