¿Qué significa que el espacio de nombres global estaría contaminado?

Respuestas:

124

Nota rápida sobre la recolección de basura

A medida que las variables pierden alcance, serán elegibles para la recolección de basura. Si tienen un alcance global, no serán elegibles para la recopilación hasta que el espacio de nombres global pierda el alcance.

Aquí hay un ejemplo:

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

Agregar esto a su espacio de nombres global (al menos para mí) debería generar 10,000 kb de uso de memoria (win7 firefox) que no se recopilarán. Otros navegadores pueden manejar esto de manera diferente.

Considerando que tener ese mismo código en un alcance que sale del alcance como este:

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

Permitirá arraperder alcance después de que se ejecute el cierre y será elegible para la recolección de basura.

El espacio de nombres global es tu amigo

A pesar de las muchas afirmaciones contra el uso del espacio de nombres global, es su amigo. Y como buen amigo, no debes abusar de tu relación.

Sé gentil

No abuse (generalmente denominado "contaminar") el espacio de nombres global. Y lo que quiero decir con no abusar del espacio de nombres global es: no crear múltiples variables globales. Este es un mal ejemplo de cómo usar el espacio de nombres 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);

Esto creará 11 variables globales que posiblemente podrían sobrescribirse o malinterpretarse en algún lugar.

Sea ingenioso

Un enfoque más ingenioso, que no contamina el espacio de nombres global, sería envolver todo esto en el patrón del módulo y solo usar una variable global mientras se exponen múltiples variables.

Aquí hay un ejemplo: (Tenga en cuenta que esto es simple y no hay manejo de errores)

//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
fuente
10
mantener las variables dentro de un cierre asegura que sean recolectadas como basura.
theJava
2
Respuesta muy interesante, ¿puede explicarnos cuál es la diferencia entre usar una devolución como lo hizo en su alcance y usar, por ejemplo, Calculate.prototype.Slope()fuera del alcance? ¡Sería muy perfecto entender otro concepto cercano a esta problemática!
Ludo
Gracias por esa buena explicación. Pregunta rápida: ¿Qué le gustaría ver sobre el manejo de errores en ese fragmento?
Sentenza
@Sentenza - Depende de lo que sucedería si hubiera un error en el futuro. Si nada, entonces realmente no necesita manejo de errores. Si es importante, entonces quizás algunas pruebas para asegurarse de que la división entre 0 no ocurra, y un mensaje o respuesta para indicar un intento fallido (a veces esto solo significa fallar silenciosamente). Quizás algunas pruebas para asegurarse de que los números sean en realidad números y no texto. Sin embargo, en general, el manejo de errores también depende de quién está usando el código. Si eres solo tú, probablemente sabrás que no debes aprobar ciertos argumentos de ruptura. Este es también un ejemplo bastante simple :)
Travis J
20

En JavaScript, las declaraciones fuera de una función están en el ámbito global. Considere este pequeño ejemplo:

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

En el ejemplo anterior, xse declara en el ámbito global. Cualquier ámbito secundario, como el creado por la examplefunción, hereda efectivamente las cosas declaradas en cualquier ámbito principal (en este caso, es solo el ámbito global).

Cualquier ámbito secundario que vuelva a declarar una variable declarada en el ámbito global sombreará la variable global, lo que podría causar errores no deseados y difíciles de rastrear:

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

Por lo general, las variables globales no se recomiendan debido a la posibilidad de causar problemas como este. Si no usáramos la vardeclaración dentro de la examplefunción, accidentalmente habríamos sobrescrito el valor de xen el alcance 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

Si desea leer más y comprenderlo correctamente, le sugiero que revise la especificación ECMAScript . Puede que no sea la más emocionante de las lecturas, pero será de gran ayuda.

James Allardice
fuente
8

Cuando declaras variables globales, funciones, etc., ellas, ehm, van al espacio de nombres global. Aparte de los problemas de rendimiento / memoria (que pueden surgir), es probable que se encuentre con un desafortunado conflicto de nombres, cuando redefina una variable importante o no use el valor que cree que usa.

Debe evitarse definir cosas en el espacio de nombres global.

Sergio Tulentsev
fuente
1
Una forma de evitar definir cosas en el espacio de nombres global es usar variables locales (declaradas con "var" dentro de una función), pero luego la variable es ... local a la función. Esto debe hacerse tanto como sea posible.
Stéphane Glondu