You can delete properties of an object while you're running a for loop over that object. No special tricks are required.
If you delete a property that's already been iterated (including the current iteration), nothing special happens - the iteration continues on its merry way. If you delete a property that hasn't yet been iterated, it won't be. Just for fun, here's a primitive little cache implementation that lets you add/remove/get items and also prune items from the beginning of the list: function Cache() { var itemsByKey = {}; var keysByIndex = []; this.add = function( key, value ) { var item = itemsByKey[key]; if( item ) { item.value = value; } else { itemsByKey[key] = { value: value, index: keysByIndex.length }; keysByIndex.push( key ); } }; this.remove = function( key ) { var item = itemsByKey[key]; if( item ) { keysByIndex.splice( item.index, 1 ); delete itemsByKey[key]; } }; this.get = function( key ) { var item = itemsByKey[key]; return item && item.value; }; this.prune = function( n ) { n = Math.min( n, keysByIndex.length ); for( var i = 0; i < n; ++i ) { delete itemsByKey[ keysByIndex[i] ]; } keysByIndex.splice( 0, n ); }; // for testing this.dump = function() { console.debug( keysByIndex, itemsByKey ); }; } var c = new Cache; c.add('a','A'); c.add('b','B'); c.add('c','C'); c.add('d','D'); c.dump(); console.debug( c.get('b') ); c.add('b','BB'); // duplicate key console.debug( c.get('b') ); c.dump(); c.remove('b'); console.debug( c.get('b') ); c.dump(); c.prune(2); c.dump(); Pasted into the Firebug multiline console, this should dump: ["a", "b", "c", "d"] Object a=Object b=Object c=Object d=Object B BB ["a", "b", "c", "d"] Object a=Object b=Object c=Object d=Object undefined ["a", "c", "d"] Object a=Object c=Object d=Object ["d"] Object d=Object -Mike > From: Pops > > What I wanted to use this for was my cache and to "truncate" > old data. I see that using a real array will allow me to use > the inherited .length property to set a new size and it will > do truncation. But since I am using an associated array, the > length property is no longer usable. > > So if I use the for loop with delete, will I be pulling the > "rug from under its feet?" > > Typically, in code designs like this, you would do a reverse > traversal to delete the last entries first so you can keep > with the internal loop counters and/or references. > > In other words, is this "safe?" > > function pruneCache(amt) { > var n = 0; > for (var i in cache) { > if (amt > 0) { > amt--; > delete cache[i]; > return; > } > n++; > } > cache.length = n; > } > > If not, then in lieu of a reverse loop syntax, I would probably need > to copy the cache first? I have not checked but if returning false > stops the traveral that would be more efficient. > > I could recode all this into a pure indexed array and then > use the .length, but then I would need a fast lookup method > or 2nd matrix to map the associated name with the array index.