Comment effacer rapidement un objet Javascript?

Avec une matrice Javascript, je peux le réinitialiser à un état vide avec une seule affectation:

array.length = 0; 

Cela rend le tableau "apparaissant" vide et prêt à réutiliser, et autant que je comprends, c'est une seule "opération" – c'est-à-dire à temps constant.

Existe-t-il un moyen similaire d'effacer un objet JS? Je sais que je peux itérer ses champs en les supprimant:

 for (var prop in obj) { if (obj.hasOwnProperty(prop)) { delete obj[prop]; } } 

Mais cela a une complexité linéaire.

Je peux aussi jeter l'objet et créer un nouveau:

 obj = {}; 

Mais la création «de promiscuité» de nouveaux objets entraîne des problèmes avec Garbage Collection sur IE6. ( Comme décrit ici )

La réponse courte à votre question, je pense, est non (vous pouvez simplement créer un nouvel objet).

  1. Dans cet exemple, je crois que le fait de définir la longueur sur 0 laisse toujours tous les éléments pour la collecte des ordures.

  2. Vous pouvez ajouter ceci à Object.prototype si c'est quelque chose que vous utiliserez fréquemment. Oui, c'est linéaire en complexité, mais tout ce qui ne fait pas la collecte des ordures plus tard sera.

  3. C'est la meilleure solution. Je sais que ce n'est pas lié à votre question, mais pour combien de temps devons-nous continuer à soutenir IE6? Il existe de nombreuses campagnes pour interrompre l'utilisation de celui-ci.

N'hésitez pas à me corriger s'il y a quelque chose de incorrect au dessus.

Eh bien, au risque de rendre les choses trop faciles …

 for (var member in myObject) delete myObject[member]; 

… semble être assez efficace pour nettoyer l'objet dans une seule ligne de code avec un minimum de brackets effrayants. Tous les membres seront vraiment supprimés au lieu de quitter les ordures.

De toute évidence, si vous souhaitez supprimer l'objet lui-même, vous devrez toujours supprimer séparément () pour cela.

ES5

La solution ES5 peut être

 // for enumerable properties Object.keys(obj).forEach(function (prop) { delete obj[prop]; }); // for all properties Object.getOwnPropertyNames(obj).forEach(function (prop) { delete obj[prop]; }); 

ES6

Et la solution ES6 peut être

 // for enumerable properties for (const prop of Object.keys(obj)) { delete obj[prop]; } // for all properties for (const prop of Object.getOwnPropertyNames(obj)) { delete obj[prop]; } 

Performance

Indépendamment des spécifications, les solutions les plus rapides seront généralement

 // for enumerable properties var props = Object.keys(obj); for (var i = 0; i < props.length; i++) { delete obj[props[i]]; } // for all properties of an object with proto chain var props = Object.getOwnPropertyNames(obj); for (var i = 0; i < props.length; i++) { delete obj[props[i]]; } // for all properties of shallow/plain object for (var key in obj) { // this check can be safely omitted in modern JS engines // if (obj.hasOwnProperty(key)) delete obj[key]; } 

Donc, pour récapituler votre question: vous souhaitez éviter, dans la mesure du possible, des problèmes avec IE6 GC bug. Ce bug comporte deux causes:

  1. La collecte des ordures se produit une fois toutes les allocations ; Par conséquent, plus les allocations que vous faites, le GC plus fréquent sera exécuté;
  2. Plus il y a d'objets que vous avez dans l'air, plus le temps de chaque collecte de Garbage Collection prend (car il va parcourir toute la liste d'objets pour voir ceux qui sont marqués comme des ordures).

La solution pour provoquer 1 semble être: conserver le nombre d'allocations vers le bas; Assigner les nouveaux objets et les chaînes le moins possible.

La solution à provoquer 2 semble être: garder le nombre d'objets "en direct" vers le bas; Supprimez vos chaînes et vos objets dès que vous n'en avez plus besoin, et créez-les de nouveau lorsque cela est nécessaire.

Dans une certaine mesure, ces solutions sont contradictoires: garder le nombre d'objets en mémoire faible entraînera plus d'allocations et de désaffectations. À l'inverse, la réutilisation constante des mêmes objets pourrait signifier garder plus d'objets en mémoire que strictement nécessaire.


Maintenant pour votre question. Que vous réinitialiez un objet en créant un nouveau, ou en supprimant toutes ses propriétés: cela dépendra de ce que vous voulez faire avec lui par la suite.

Vous voudrez probablement lui attribuer de nouvelles propriétés:

  • Si vous le faites immédiatement, je suggère d'assigner les nouvelles propriétés immédiatement et de sauter la suppression ou la suppression d'abord. (Assurez-vous que toutes les propriétés sont soit écrasées, soit supprimées, cependant!)
  • Si l'objet ne sera pas utilisé immédiatement, mais sera repeuplé à un stade ultérieur, je suggère de le supprimer ou de l'attribuer nulle, et de créer un nouveau plus tard.

Il n'y a pas de moyen rapide, facile à utiliser pour effacer un objet JScript pour réutiliser comme s'il s'agissait d'un nouvel objet – sans en créer un. Ce qui signifie que la réponse courte à votre question est «Non», comme le dit Jthompson.

Quelque chose de nouveau à penser à l'attente de Object.observe dans ES7 et à la liaison de données en général. Considérer:

 var foo={ name: "hello" }; Object.observe(foo, function(){alert('modified');}); // bind to foo foo={}; // You are no longer bound to foo but to an orphaned version of it foo.name="there"; // This change will be missed by Object.observe() 

Donc dans cette circonstance n ° 2 peut être le meilleur choix.

Vous pouvez essayer cela. La fonction ci-dessous définit toutes les valeurs des propriétés de l'objet sur undefined. Fonctionne également avec des objets imbriqués.

 var clearObjectValues = (objToClear) => { Object.keys(objToClear).forEach((param) => { if ( (objToClear[param]).toString() === "[object Object]" ) { clearObjectValues(objToClear[param]); } else { objToClear[param] = undefined; } }) return objToClear; }; 

Vous pouvez supprimer les accessoires, mais ne pas supprimer les variables. delete abc; Est invalide dans ES5 (et lance avec une utilisation stricte).

Vous pouvez l'attribuer à null pour le définir pour la suppression du GC (ce ne sera pas si vous avez d'autres références aux propriétés)

La propriété Setting length sur un objet ne change rien. (Seulement, bien, définit la propriété)

Nous pouvons le faire de manière écrite.

Obj.slice (0,0)

Simplement faites:

 myObject = {}; 

Cela effacera l'objet de ses valeurs.

Cela semble fonctionner:

 obj = {someKey: 'someValue'} Object.keys(obj).length = 0