Küresel ad alanının kirleneceği ne anlama geliyor?


92

Küresel ad alanının kirleneceği ne anlama geliyor?

Küresel ad alanının kirlenmesinin ne anlama geldiğini gerçekten anlamıyorum.


1
İleride referans olması için bağlantı oluşturma: JavaScript Ad Alanı Bildirimi
blong

Yanıtlar:


124

Çöp Toplama Hakkında Hızlı Not

Değişkenler kapsamını yitirdikçe, çöp toplama için uygun olacaktır. Kapsamı genel olarak belirlenmişse, genel ad alanı kapsamını kaybedene kadar koleksiyon için uygun olmayacaktır.

İşte bir örnek:

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

Bunu genel ad alanınıza eklemek (en azından benim için) toplanmayacak 10.000 kb bellek kullanımı (win7 firefox) eklemelidir. Diğer tarayıcılar bunu farklı şekilde ele alabilir.

Oysa aynı koda şu şekilde kapsam dışında kalan bir kapsamda sahip olmak:

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

arraKapanış çalıştırıldıktan sonra kapsamın kaybolmasına izin verecek ve çöp toplama için uygun olacaktır.

Global Ad Alanı Arkadaşınızdır

Küresel ad alanını kullanmayla ilgili birçok iddiaya rağmen, bu senin arkadaşın. Ve iyi bir arkadaş gibi, ilişkinizi kötüye kullanmamalısınız.

Nazik olmak

Genel ad alanını kötüye kullanmayın (genellikle "kirletme" olarak anılır). Ve küresel ad alanını kötüye kullanma ile kastettiğim - birden çok global değişken oluşturmayın. İşte global ad alanını kullanmanın kötü bir örneği.

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

Bu, muhtemelen üzerine yazılabilecek veya bir yerde yanlış yorumlanabilecek 11 küresel değişken oluşturacak.

Becerikli Olun

Global isim alanını kirletmeyen daha becerikli bir yaklaşım, hepsini modül modeline sarmak ve birden çok değişkeni açığa çıkarırken yalnızca bir global değişken kullanmak olacaktır.

İşte bir örnek: (Lütfen bunun basit olduğunu ve herhangi bir hata işleme olmadığını unutmayın)

//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
değişkenlerin bir kapanış içinde tutulması, bunların çöp olarak toplanmasını sağlar.
theJava

2
Çok ilginç cevap, kapsamınızda yaptığınız gibi bir dönüş kullanarak örneğin Calculate.prototype.Slope()kapsam dışında kullanmak arasındaki farkı bize açıklayabilir misiniz ? Bu problematiğe yakın başka bir kavramı anlamak çok mükemmel olurdu!
Kızma Birader

Bu güzel açıklama için teşekkürler. Kısa soru: Bu ön bilgide hata işleme hakkında ne görmek istersiniz?
Sentenza

@Sentenza - Hattın altında bir hata olsaydı ne olacağına bağlı. Hiçbir şey yoksa, o zaman gerçekten hata işlemeye ihtiyaç duymaz. Önemliyse, 0'a bölmenin gerçekleşmediğinden emin olmak için bazı testler ve başarısız bir girişimi belirtmek için bir mesaj veya yanıt (bazen bu sadece sessizce başarısız olmak anlamına gelir). Belki de sayıların metin değil sayı olduğundan emin olmak için bazı testler. Genel olarak, hata işleme aynı zamanda kodu kimin kullandığına da bağlıdır. Eğer sadece siz iseniz, muhtemelen bazı kırılma argümanlarını geçmemeniz gerektiğini bileceksiniz. Bu da oldukça basit bir örnek :)
Travis J

20

JavaScript'te, bir işlevin dışındaki bildirimler genel kapsamdadır. Şu küçük örneği düşünün:

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

Yukarıdaki örnekte x, genel kapsamda beyan edilmiştir. exampleİşlev tarafından oluşturulanlar gibi herhangi bir alt kapsam, herhangi bir üst kapsamda bildirilen şeyleri etkin bir şekilde devralır (bu durumda, bu yalnızca genel kapsamdır).

Genel kapsamda bildirilen bir değişkeni yeniden bildiren herhangi bir alt kapsam, genel değişkeni gölgeleyecek ve potansiyel olarak istenmeyen, izlenmesi zor hatalara neden olacaktır:

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

Küresel değişkenler, böyle sorunlara neden olma potansiyeli nedeniyle genellikle tavsiye edilmez. Fonksiyonun variçindeki ifadeyi kullanmasaydık, exampleyanlışlıkla xgenel kapsamdaki değerinin üzerine yazmış olurduk :

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

Daha fazlasını okumak ve doğru bir şekilde anlamak istiyorsanız, ECMAScript spesifikasyonunu incelemenizi öneririm . Okumaların en heyecan verici kısmı olmayabilir ama sonu gelmez.


8

Global değişkenleri, fonksiyonları vb. Bildirdiğinizde, bunlar, ehm, global ad alanına gider. Performans / bellek sorunlarının yanı sıra (ortaya çıkabilecek), önemli bir değişkeni yeniden tanımladığınızda veya kullandığınızı düşündüğünüz değeri kullanmayacağınız zaman, talihsiz bir ad çatışmasıyla karşılaşmanız muhtemeldir.

Global isim alanındaki şeyleri tanımlamaktan kaçınılmalıdır.


1
Global isim alanındaki şeyleri tanımlamaktan kaçınmanın bir yolu, yerel değişkenler kullanmaktır (bir fonksiyonun içinde "var" ile bildirilen), ancak bu durumda değişken fonksiyon için ... yereldir. Bu mümkün olduğu kadar yapılmalıdır.
Stéphane Glondu
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.