¿Cómo puedo desarmar una variable de JavaScript?

Resuelto Guss asked hace 15 años • 13 respuestas

Tengo una variable global en JavaScript (en realidad unawindow propiedad, pero no creo que importe) que ya estaba poblada por un script anterior, pero no quiero que se ejecute otro script más tarde para ver su valor o que fue incluso definido.

Lo he puesto some_var = undefinedy funciona con fines de prueba.typeof some_var == "undefined" , pero realmente no creo que sea la forma correcta de hacerlo.

¿Qué opinas?

Guss avatar Oct 21 '09 02:10 Guss
Aceptado

Eldelete operador elimina una propiedad de un objeto. No puede eliminar una variable. Entonces, la respuesta a la pregunta depende de cómo se define la variable o propiedad global.

(1) Si se crea convar , no se puede eliminar.

Por ejemplo:

var g_a = 1; //create with var, g_a is a variable
delete g_a; //return false
console.log(g_a); //g_a is still 1

(2) Si se crea sin var, se puede eliminar.

g_b = 1; //create without var, g_b is a property
delete g_b; //return true
console.log(g_b); //error, g_b is not defined

Explicación técnica

1. Usandovar

En este caso, la referencia g_ase crea en lo que la especificación ECMAScript llama " VariableEnvironment " que se adjunta al alcance actual; este puede ser el contexto de ejecución de una función en el caso de usarla vardentro de una función (aunque puede volverse un poco más complicado). cuando se considera let) o en el caso de código "global", el entorno variable se adjunta al objeto global (a menudowindow ).

Las referencias en VariableEnvironment normalmente no se pueden eliminar; el proceso detallado en ECMAScript 10.5 explica esto en detalle, pero basta decir que, a menos que su código se ejecute en un evalcontexto (que usan la mayoría de las consolas de desarrollo basadas en navegador), las variables declaradas convar no se pueden eliminar. ser eliminado.

2. Sin usarvar

Al intentar asignar un valor a un nombre sin usar la varpalabra clave, JavaScript intenta ubicar la referencia nombrada en lo que la especificación ECMAScript llama " LexicalEnvironment ", y la principal diferencia es que los LexicalEnvironment están anidados, es decir, un LexicalEnvironment tiene un padre ( lo que la especificación ECMAScript llama "referencia de entorno externo") y cuando JavaScript no logra ubicar la referencia en un LexicalEnvironment , busca en el LexicalEnvironment principal (como se detalla en 10.3.1 y 10.2.2.1 ). El LexicalEnvironment de nivel superior es el " entorno global ", y está vinculado al objeto global en el sentido de que sus referencias son las propiedades del objeto global. Entonces, si intenta acceder a un nombre que no fue declarado usando una varpalabra clave en el alcance actual o en cualquier alcance externo, JavaScript eventualmente obtendrá una propiedad del windowobjeto para que sirva como referencia. Como aprendimos antes, las propiedades de los objetos se pueden eliminar.

Notas

  1. Es importante recordar que varlas declaraciones se "elevan", es decir, siempre se considera que han ocurrido al principio del alcance en el que se encuentran, aunque no la inicialización del valor que se puede realizar en una vardeclaración, que se deja donde está. . Entonces, en el siguiente código, ahay una referencia del VariableEnvironment y no la windowpropiedad y su valor estará 10al final del código:

    function test() { a = 5; var a = 10; }
    
  2. La discusión anterior es cuando el "modo estricto" no está habilitado. Las reglas de búsqueda son un poco diferentes cuando se usa el "modo estricto" y las referencias léxicas que se habrían resuelto en las propiedades de la ventana sin el "modo estricto" generarán errores de "variable no declarada" en el "modo estricto". Realmente no entendí dónde se especifica esto, pero así es como se comportan los navegadores.

Dayong avatar Sep 18 '2014 18:09 Dayong

La respuesta de scunliffe funcionará, pero técnicamente debería serlo.

delete window.some_var;

Se supone que eliminar no es operativo cuando el objetivo no es una propiedad del objeto. p.ej,

(function() {
   var foo = 123;
   delete foo; // wont do anything, foo is still 123
   var bar = { foo: 123 };
   delete bar.foo; // foo is gone
}());

Pero como las variables globales son en realidad miembros del objeto ventana, funciona.

Cuando se trata de cadenas de prototipos, el uso de eliminar se vuelve más complejo porque solo elimina la propiedad del objeto de destino, y no el prototipo. p.ej,

function Foo() {}
Foo.prototype = { bar: 123 };
var foo = new Foo();
// foo.bar is 123
foo.bar = 456;
// foo.bar is now 456
delete foo.bar;
// foo.bar is 123 again.

Así que ten cuidado.

Nota: Mi respuesta es algo inexacta (consulte "Conceptos erróneos" al final). El enlace explica todos los detalles sangrientos, pero el resumen es que puede haber grandes diferencias entre los navegadores y dependiendo del objeto que esté eliminando. delete object.somePropEn general, debería ser seguro siempre que object !== window. Todavía no lo usaría para eliminar variables declaradas, varaunque puedes hacerlo en las circunstancias adecuadas.

noah avatar Oct 20 '2009 19:10 noah

Si está declarando implícitamente la variable sin var, la forma correcta sería usar delete foo.

Sin embargo, después de eliminarlo, si intenta utilizarlo en una operación como la suma, ReferenceErrorse generará a porque no puede agregar una cadena a un identificador no declarado ni definido. Ejemplo:

x = 5;
delete x
alert('foo' + x )
// ReferenceError: x is not defined

Puede ser más seguro en algunas situaciones asignarlo a falso, nulo o indefinido para que se declare y no arroje este tipo de error.

foo = false

Tenga en cuenta que en ECMAScript null, false, undefined, 0, NaNo ''todos se evaluarían como false. Solo asegúrese de no utilizar el !==operador, sino !=cuando escriba la verificación de valores booleanos y no desee verificar la identidad (lo mismo nullharía == falsey false == undefined).

También tenga en cuenta que deleteno "elimina" referencias sino solo propiedades directamente en el objeto, por ejemplo:

bah = {}, foo = {}; bah.ref = foo;

delete bah.ref;
alert( [bah.ref, foo ] )
// ,[object Object] (it deleted the property but not the reference to the other object)

Si ha declarado una variable con varno puede eliminarla:

(function() {
    var x = 5;
    alert(delete x)
    // false
})();

En rinoceronte:

js> var x
js> delete x
false

Tampoco puede eliminar algunas propiedades predefinidas como Math.PI:

js> delete Math.PI
false

Hay algunas excepciones extrañas, deletecomo ocurre con cualquier idioma, si te importa lo suficiente, deberías leer:

  • https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Operators/Special_Operators/delete_Operator
  • http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf
meder omuraliev avatar Oct 20 '2009 19:10 meder omuraliev