¿Cómo puedo desarmar una variable de JavaScript?
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 = undefined
y funciona con fines de prueba.typeof some_var == "undefined"
, pero realmente no creo que sea la forma correcta de hacerlo.
¿Qué opinas?
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
var
En este caso, la referencia g_a
se 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 var
dentro 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 eval
contexto (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 var
palabra 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 var
palabra clave en el alcance actual o en cualquier alcance externo, JavaScript eventualmente obtendrá una propiedad del window
objeto para que sirva como referencia. Como aprendimos antes, las propiedades de los objetos se pueden eliminar.
Notas
Es importante recordar que
var
las 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 unavar
declaración, que se deja donde está. . Entonces, en el siguiente código,a
hay una referencia del VariableEnvironment y no lawindow
propiedad y su valor estará10
al final del código:function test() { a = 5; var a = 10; }
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.
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.someProp
En general, debería ser seguro siempre que object !== window
. Todavía no lo usaría para eliminar variables declaradas, var
aunque puedes hacerlo en las circunstancias adecuadas.
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, ReferenceError
se 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
, NaN
o ''
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 null
haría == false
y false == undefined
).
También tenga en cuenta que delete
no "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 var
no 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, delete
como 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