Apa artinya namespace global akan tercemar?

92

Apa artinya namespace global akan tercemar?

Saya tidak begitu mengerti apa arti namespace global yang tercemar.

theJava
sumber
1
Menautkan untuk referensi di masa mendatang: Deklarasi Ruang Nama JavaScript
blong

Jawaban:

124

Catatan Cepat Mengenai Pengumpulan Sampah

Karena variabel kehilangan ruang lingkup, mereka akan memenuhi syarat untuk pengumpulan sampah. Jika cakupannya secara global, maka mereka tidak akan memenuhi syarat untuk pengumpulan sampai namespace global kehilangan cakupan.

Berikut ini contohnya:

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

Menambahkan ini ke namespace global Anda (setidaknya untuk saya) harus menambahkan 10.000 kb penggunaan memori (win7 firefox) yang tidak akan dikumpulkan. Browser lain mungkin menangani ini secara berbeda.

Padahal memiliki kode yang sama dalam ruang lingkup yang keluar dari ruang lingkup seperti ini:

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

Akan memungkinkan arrakehilangan ruang lingkup setelah penutupan dijalankan dan memenuhi syarat untuk pengumpulan sampah.

Namespace Global Adalah Teman Anda

Meskipun ada banyak klaim yang menentang penggunaan namespace global, itu adalah teman Anda. Dan seperti seorang teman baik, Anda tidak boleh menyalahgunakan hubungan Anda.

Bersikaplah Lembut

Jangan menyalahgunakan (biasanya disebut sebagai "mencemari") namespace global. Dan yang saya maksud dengan jangan menyalahgunakan namespace global adalah - jangan membuat banyak variabel global. Berikut adalah contoh buruk penggunaan namespace global.

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

Ini akan membuat 11 variabel global yang mungkin bisa ditimpa atau disalahartikan di suatu tempat.

Jadilah Banyak Akal

Pendekatan yang lebih banyak akal, yang tidak mencemari namespace global, akan membungkus ini semua dalam pola modul dan hanya menggunakan satu variabel global sambil mengekspos beberapa variabel.

Berikut ini contohnya: (Harap dicatat ini sederhana dan tidak ada penanganan kesalahan)

//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
sumber
10
menjaga variabel di dalam closure memastikan mereka sampah dikumpulkan.
theJava
2
Jawaban yang sangat menarik, dapatkah Anda menjelaskan kepada kami apa perbedaan betwwen menggunakan pengembalian seperti yang Anda lakukan di ruang lingkup Anda, dan menggunakan misalnya di Calculate.prototype.Slope()luar ruang lingkup? Akan sangat sempurna untuk memahami konsep lain yang mendekati masalah ini!
Ludo
Terima kasih atas penjelasan yang bagus itu. Pertanyaan singkat: Apa yang ingin Anda lihat tentang penanganan kesalahan dalam cuplikan itu?
Sentenza
@ Sentenza - Itu tergantung pada apa yang akan terjadi jika ada kesalahan di telepon. Jika tidak ada, maka benar-benar tidak perlu penanganan kesalahan. Jika penting, mungkin beberapa pengujian untuk memastikan bahwa pembagian dengan 0 tidak terjadi, dan pesan atau respons untuk menunjukkan upaya yang gagal (terkadang ini hanya berarti gagal diam-diam). Mungkin beberapa tes untuk memastikan bahwa angka sebenarnya adalah angka dan bukan teks. Secara keseluruhan, penanganan error juga tergantung pada siapa yang menggunakan kode tersebut. Jika hanya Anda, Anda mungkin tahu untuk tidak menyampaikan argumen yang melanggar. Ini juga contoh yang agak sederhana :)
Travis J
20

Di JavaScript, deklarasi di luar fungsi berada dalam cakupan global. Pertimbangkan contoh kecil ini:

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

Dalam contoh di atas, xdideklarasikan dalam lingkup global. Setiap cakupan anak, seperti yang dibuat oleh examplefungsi, secara efektif mewarisi hal-hal yang dideklarasikan dalam cakupan induk mana pun (dalam hal ini, itu hanya cakupan global).

Setiap cakupan anak yang mendeklarasikan ulang variabel yang dideklarasikan dalam cakupan global akan membayangi variabel global, berpotensi menyebabkan bug yang tidak diinginkan dan sulit dilacak:

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

Variabel global biasanya tidak direkomendasikan karena berpotensi menimbulkan masalah seperti ini. Jika kami tidak menggunakan varpernyataan di dalam examplefungsi, kami akan secara tidak sengaja menimpa nilai xdalam cakupan global:

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

Jika Anda ingin membaca lebih lanjut dan memahaminya dengan benar, saya sarankan untuk membaca spesifikasi ECMAScript . Ini mungkin bukan bacaan yang paling menarik, tetapi itu tidak akan membantu.

James Allardice
sumber
8

Saat Anda mendeklarasikan variabel global, fungsi, dll., Mereka, ehm, pergi ke namespace global. Selain dari masalah kinerja / memori (yang mungkin timbul), Anda mungkin akan mengalami bentrok nama yang tidak menguntungkan, ketika Anda akan mendefinisikan ulang variabel penting atau tidak menggunakan nilai yang Anda pikir Anda gunakan.

Mendefinisikan hal-hal di namespace global harus dihindari.

Sergio Tulentsev
sumber
1
Sebuah cara untuk menghindari pendefinisian sesuatu dalam namespace global adalah dengan menggunakan variabel lokal (dideklarasikan dengan "var" di dalam sebuah fungsi), tetapi kemudian variabel tersebut adalah ... lokal ke fungsi tersebut. Ini harus dilakukan semaksimal mungkin.
Stéphane Glondu