Điều đó có nghĩa là không gian tên toàn cầu sẽ bị ô nhiễm?


92

Điều đó có nghĩa là không gian tên toàn cầu sẽ bị ô nhiễm?

Tôi không thực sự hiểu không gian tên toàn cầu bị ô nhiễm nghĩa là gì.


1
Liên kết để tham khảo trong tương lai:
Khai báo

Câu trả lời:


124

Ghi chú nhanh về việc thu gom rác

Khi các biến mất phạm vi, chúng sẽ đủ điều kiện để thu gom rác. Nếu chúng nằm trong phạm vi toàn cầu, thì chúng sẽ không đủ điều kiện để thu thập cho đến khi không gian tên chung mất phạm vi.

Đây là một ví dụ:

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

Thêm điều này vào không gian tên chung của bạn (ít nhất là đối với tôi) sẽ quảng cáo 10.000 kb bộ nhớ sử dụng (win7 firefox) sẽ không được thu thập. Các trình duyệt khác có thể xử lý điều này theo cách khác.

Trong khi có cùng một mã trong một phạm vi nằm ngoài phạm vi như thế này:

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

Sẽ cho phép arramất phạm vi sau khi quá trình đóng thực thi và đủ điều kiện để thu gom rác.

Không gian tên toàn cầu là bạn của bạn

Bất chấp nhiều tuyên bố chống lại việc sử dụng không gian tên chung, nó là bạn của bạn. Và giống như một người bạn tốt, bạn không nên lạm dụng mối quan hệ của mình.

Hãy nhẹ nhàng

Không lạm dụng (thường được gọi là "gây ô nhiễm") không gian tên chung. Và điều tôi muốn nói là không lạm dụng không gian tên toàn cục - không tạo nhiều biến toàn cục. Đây là một ví dụ tồi về việc sử dụng không gian tên chung.

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

Điều này sẽ tạo ra 11 biến toàn cục có thể bị ghi đè hoặc thông qua sai ở đâu đó.

Hãy tháo vát

Một cách tiếp cận hiệu quả hơn, không gây ô nhiễm không gian tên chung, sẽ là gói tất cả điều này trong mô-đun và chỉ sử dụng một biến toàn cục trong khi hiển thị nhiều biến.

Đây là một ví dụ: (Xin lưu ý rằng điều này rất đơn giản và không có lỗi xử lý)

//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
giữ các biến bên trong một bao đóng để đảm bảo chúng được thu thập rác.
theJava,

2
Câu trả lời rất thú vị, bạn có thể giải thích cho chúng tôi sự khác biệt giữa cách sử dụng trả về như bạn đã làm trong phạm vi của mình và sử dụng ví dụ Calculate.prototype.Slope()bên ngoài phạm vi không? Sẽ rất hoàn hảo nếu hiểu rõ một khái niệm khác gần với vấn đề này!
Ludo

Cảm ơn vì lời giải thích tốt. Câu hỏi nhanh: Bạn muốn thấy gì về xử lý lỗi trong đoạn mã đó?
Sentenza

@Sentenza - Nó phụ thuộc vào điều gì sẽ xảy ra nếu có lỗi ở dòng dưới. Nếu không có gì, thì nó thực sự không cần xử lý lỗi. Nếu điều đó là quan trọng, thì có lẽ một số thử nghiệm để đảm bảo rằng phép chia cho 0 không xảy ra và một thông báo hoặc phản hồi để chỉ ra một nỗ lực không thành công (đôi khi điều này chỉ có nghĩa là thất bại âm thầm). Có lẽ một số thử nghiệm để đảm bảo rằng số thực sự là số chứ không phải văn bản. Nhìn chung, việc xử lý lỗi cũng phụ thuộc vào người đang sử dụng mã. Nếu chỉ là bạn, bạn có thể sẽ biết không vượt qua một số lập luận vi phạm nhất định. Đây cũng là một ví dụ khá đơn giản :)
Travis J

20

Trong JavaScript, các khai báo bên ngoài một hàm nằm trong phạm vi toàn cục. Hãy xem xét ví dụ nhỏ này:

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

Trong ví dụ trên, xđược khai báo trong phạm vi toàn cục. Bất kỳ phạm vi con nào, chẳng hạn như phạm vi được tạo bởi examplehàm, kế thừa hiệu quả những thứ được khai báo trong bất kỳ phạm vi cha nào (trong trường hợp này, đó chỉ là phạm vi toàn cục).

Bất kỳ phạm vi con nào khai báo lại một biến được khai báo trong phạm vi toàn cục sẽ làm mờ biến toàn cục, có khả năng gây ra các lỗi không mong muốn, khó theo dõi:

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

Các biến toàn cục thường không được khuyến khích vì có khả năng gây ra các vấn đề như thế này. Nếu chúng tôi không sử dụng varcâu lệnh bên trong examplehàm, chúng tôi sẽ vô tình ghi đè giá trị của xtrong phạm vi toàn cục:

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

Nếu bạn muốn đọc thêm và hiểu nó đúng cách, tôi khuyên bạn nên xem qua đặc tả ECMAScript . Nó có thể không phải là thú vị nhất trong số những lần đọc nhưng nó sẽ không có hồi kết.


8

Khi bạn khai báo các biến toàn cục, hàm, v.v., chúng sẽ chuyển đến không gian tên toàn cục. Ngoài các vấn đề về hiệu suất / bộ nhớ (có thể phát sinh), bạn có thể gặp phải xung đột tên đáng tiếc, khi bạn xác định lại một biến quan trọng hoặc không sử dụng giá trị mà bạn nghĩ rằng bạn sử dụng.

Việc xác định những thứ trong không gian tên chung là điều nên tránh.


1
Một cách để tránh xác định mọi thứ trong không gian tên toàn cục là sử dụng các biến cục bộ (được khai báo bằng "var" bên trong một hàm), nhưng sau đó biến là ... cục bộ của hàm. Điều này nên được thực hiện càng nhiều càng tốt.
Stéphane Glondu
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.