Iterate over object keys in node.js


Question

Since Javascript 1.7 there is an Iterator object, which allows this:

var a={a:1,b:2,c:3};
var it=Iterator(a);

function iterate(){
    try {  
        console.log(it.next());
        setTimeout(iterate,1000);
    }catch (err if err instanceof StopIteration) {  
        console.log("End of record.\n");  
    } catch (err) {  
        console.log("Unknown error: " + err.description + "\n");  
    }  

}
iterate();

is there something like this in node.js ?

Right now i'm using:

function Iterator(o){
    /*var k=[];
    for(var i in o){
        k.push(i);
    }*/
    var k=Object.keys(o);
    return {
        next:function(){
            return k.shift();
        }
    };
}

but that produces a lot of overhead by storing all the object keys in k.

1
127
9/16/2011 8:40:25 AM

Accepted Answer

What you want is lazy iteration over an object or array. This is not possible in ES5 (thus not possible in node.js). We will get this eventually.

The only solution is finding a node module that extends V8 to implement iterators (and probably generators). I couldn't find any implementation. You can look at the spidermonkey source code and try writing it in C++ as a V8 extension.

You could try the following, however it will also load all the keys into memory

Object.keys(o).forEach(function(key) {
  var val = o[key];
  logic();
});

However since Object.keys is a native method it may allow for better optimisation.

Benchmark

As you can see Object.keys is significantly faster. Whether the actual memory storage is more optimum is a different matter.

var async = {};
async.forEach = function(o, cb) {
  var counter = 0,
    keys = Object.keys(o),
    len = keys.length;
  var next = function() {
    if (counter < len) cb(o[keys[counter++]], next);
  };
  next();
};

async.forEach(obj, function(val, next) {
  // do things
  setTimeout(next, 100);
});
225
2/17/2015 3:34:21 PM

Also remember that you can pass a second argument to the .forEach() function specifying the object to use as the this keyword.

// myOjbect is the object you want to iterate.
// Notice the second argument (secondArg) we passed to .forEach.
Object.keys(myObject).forEach(function(element, key, _array) {
  // element is the name of the key.
  // key is just a numerical value for the array
  // _array is the array of all the keys

  // this keyword = secondArg
  this.foo;
  this.bar();
}, secondArg);

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon