Eliminar objetos en JavaScript

359

Estoy un poco confundido con el deleteoperador de JavaScript . Tome el siguiente código:

var obj = {
    helloText: "Hello World!"
};

var foo = obj;

delete obj;

Después de que este fragmento de código se haya ejecutado, objes null, pero fooaún se refiere a un objeto exactamente igual obj. Supongo que este objeto es el mismo objeto que fooseñaló.

Esto me confunde, porque esperaba que la escritura delete objeliminara el objeto que objapuntaba en la memoria, no solo la variable obj.

Se debe esto a la basura de JavaScript Collector está trabajando en una base retener / liberación, por lo que si no tuviera ninguna otra variable que apunta al objeto, que podría ser eliminado de la memoria?

(Por cierto, mi prueba se realizó en Safari 4.)

Steve Harrison
fuente
77
Para tu referencia. developer.mozilla.org/en/Core_JavaScript_1.5_Reference/…
Daniel A. White
Artículo completo sobre la palabra clave eliminar webcache.googleusercontent.com/…
Vitim.us
2
El enlace de arriba debe ser: perfectionkills.com/understanding-delete
johnmdonahue
1
@Steve Harrison delete no es para eliminar un objeto en javascript eliminar el uso para eliminar una clave de objeto en su caso, el var obj = { helloText: "Hello World!" }; var foo = obj; delete obj;objeto no se elimina verificar objeliminar el uso: delete obj.helloTexty luego verificarfoo now foo is an empty object
Umair Ahmed
2
@UmairAhmed, traducción gratuita: "" " deleteno es para eliminar objetos en javascript. deleteSe utiliza para eliminar una clave de objeto. En su caso var obj = { helloText: "Hello World!" }; var foo = obj; delete obj;, el objeto no se elimina. Compruebe obj. A continuación, ejecute delete obj.helloTexty puede ver que fooahora apunta a un vacío objeto. "" "
Pacerier

Respuestas:

448

El operador de eliminación elimina solo una referencia, nunca un objeto en sí. Si eliminó el objeto en sí, otras referencias restantes estarían colgando, como una eliminación de C ++. (Y acceder a uno de ellos provocaría un bloqueo. Hacer que todos se vuelvan nulos significaría tener un trabajo adicional al eliminar o memoria adicional para cada objeto).

Dado que Javascript es basura recolectada, no es necesario eliminar los objetos ellos mismos; se eliminarán cuando ya no haya forma de referirse a ellos.

Puede ser útil eliminar referencias a un objeto si ha terminado con él, porque esto le da al recolector de basura más información sobre lo que se puede reclamar. Si las referencias permanecen a un objeto grande, esto puede causar que no se reclame, incluso si el resto de su programa en realidad no usa ese objeto.

Jesse Rusak
fuente
23
La deletepalabra clave solo funciona para propiedades de un objeto, no para variables. perfectionkills.com/understanding-delete
Alex Mund
1
@AlexJM Sí, la siguiente respuesta de Guffa (y sus comentarios) discute esto con cierto detalle.
Jesse Rusak
1
Una propiedad de un objeto puede ser otro objeto. Por ejemplo; var obj = {a: {}}; delete obj.a;
Alex Mund
2
Pero ... ¿no son las variables realmente propiedades de window?
RedClover
3
@Soaku no variables locales. (por ejemplo, los declarados con var)
Jesse Rusak
162

El deletecomando no tiene efecto en las variables regulares, solo en las propiedades. Después del deletecomando, la propiedad no tiene el valor null, no existe en absoluto.

Si la propiedad es una referencia de objeto, el deletecomando elimina la propiedad pero no el objeto. El recolector de basura se encargará del objeto si no tiene otras referencias.

Ejemplo:

var x = new Object();
x.y = 42;

alert(x.y); // shows '42'

delete x; // no effect
alert(x.y); // still shows '42'

delete x.y; // deletes the property
alert(x.y); // shows 'undefined'

(Probado en Firefox).

Guffa
fuente
39
Si esto se ejecuta en el ámbito global, su xvariable se convierte en una propiedad del windowobjeto global y delete x;realmente elimina la xvariable por completo.
Crescent Fresh el
18
@crescentfresh: es solo una propiedad si se declara implícitamente. Si se declara explícitamente como en el ejemplo, es una variable global y no se puede eliminar.
Guffa el
44
@Tarynn: Ya veo, ahí es donde está el problema. Si hace esto en la consola, por alguna razón xno será una variable adecuada en algunos navegadores, sino una propiedad en el windowobjeto. Por supuesto, esto es un problema con la consola y no refleja cómo se ejecuta normalmente el código.
Guffa
2
@Guffa Después de un montón de investigaciones, debo admitir que probablemente fue algo bueno que no tuviera suficiente representante para rechazar el voto. Mis más sinceras disculpas, y gracias por tomarse el tiempo para mostrarme lo que estaba sucediendo ... Aquí hay una explicación en profundidad: perfectionkills.com/understanding-delete/#firebug_confusion
Tarynn
2
@chao: Ya veo. Tiene el mismo problema que Tarynn (vea los comentarios anteriores). Cuando haces esto en la consola, no funciona igual que en el código real.
Guffa
56

Las "variables declaradas implícitamente" son propiedades del objeto global, por lo que eliminar funciona en ellas como funciona en cualquier propiedad. Las variables declaradas con var son indestructibles.

Alex
fuente
53
Nunca me di cuenta de que Var era tan rudo.
Gavin
1
Este es un gran punto, y un JS tiene. Las personas se acostumbran a eliminar variables de ventana y luego se preguntan por qué no pueden hacer lo mismo con las variables locales.
welbornio
2
Lo mismo vale para let.
Pacerier
4

delete no se utiliza para eliminar un objeto en Java Script.

deleteutilizado para eliminar un object keyen su caso

var obj = { helloText: "Hello World!" }; 
var foo = obj;
delete obj;

el objeto no se elimina, compruebe que obj todavía tome los mismos valores, elimine el uso:

delete obj.helloText

y luego verifica obj, foo, ambos son objeto vacío.

Umair Ahmed
fuente
2

Acabo de encontrar un jsperf que puede considerar interesante a la luz de este asunto. (podría ser útil mantenerlo para completar la imagen)

Compara eliminar , establecer nulo y establecer indefinido .

Pero tenga en cuenta que prueba el caso cuando elimina / establece la propiedad muchas veces.

garek
fuente
1

IE 5 a 8 tiene un error en el que el uso de eliminar en las propiedades de un objeto host (Window, Global, DOM, etc.) arroja TypeError "el objeto no admite esta acción".

var el=document.getElementById("anElementId");
el.foo = {bar:"baz"};
try{
    delete el.foo;
}catch(){
    //alert("Curses, drats and double double damn!");
    el.foo=undefined; // a work around
}

Más adelante, si necesita verificar dónde la propiedad tiene un significado, use el valor completo el.foo !== undefinedporque "foo" in el siempre devolverá verdadero en IE.

Si realmente necesita que la propiedad realmente desaparezca ...

function hostProxy(host){
    if(host===null || host===undefined) return host;
    if(!"_hostProxy" in host){
       host._hostproxy={_host:host,prototype:host};
    }
    return host._hostproxy;
}
var el=hostProxy(document.getElementById("anElementId"));
el.foo = {bar:"baz"};

delete el.foo; // removing property if a non-host object

si necesita usar el objeto host con la api host ...

el.parent.removeChild(el._host);
johndhutcheson
fuente
1

Me topé con este artículo en mi búsqueda de esta misma respuesta. Lo que terminé haciendo es extraer obj.pop()todos los valores / objetos almacenados en mi objeto para poder reutilizar el objeto. No estoy seguro si esta es una mala práctica o no. Esta técnica me fue útil para probar mi código en las herramientas de Chrome Dev o FireFox Web Console.

Craig London
fuente
1

Esto funciona para mí, aunque no es una buena práctica. Simplemente elimina todo el elemento asociado al que pertenece el objeto.

 for (element in homeService) {
          delete homeService[element];
  }
Sagar de viña
fuente
¿Cuál es la mejor práctica? Recuerdo haber leído que el operador de eliminación no era la mejor práctica para eliminar propiedades de objetos. Creo que leí esto en el libro JavaScript de Crockford, pero no puedo desenterrarlo en este momento.
zero_cool
0

Establecer una variable para nullasegurarse de romper cualquier referencia a objetos en todos los navegadores, incluidas las referencias circulares que se hacen entre los elementos DOM y los ámbitos de Javascript. Al usar el deletecomando, estamos marcando los objetos que se borrarán en la próxima ejecución de la recolección de elementos no utilizados , pero si hay varias variables que hacen referencia al mismo objeto, eliminar una sola variable NO LIBERARÁ el objeto, simplemente eliminará el vínculo entre esa variable y el objeto. Y en la próxima ejecución de la recolección de basura, solo se limpiará la variable.

Pedro Justo
fuente