遍历node.js中的对象键
由于Javascript 1.7有一个Iterator对象,它允许这样做:
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();
在node.js中有这样的东西吗?
现在我正在使用:
function Iterator(o){ /*var k=[]; for(var i in o){ k.push(i); }*/ var k=Object.keys(o); return { next:function(){ return k.shift(); } }; }
但是通过将所有对象密钥存储在k
中会产生大量开销。
你想要的是懒惰迭代对象或数组。 这在ES5中是不可能的(因此在node.js中是不可能的)。 我们最终会得到这个。
唯一的解决办法是find一个扩展V8来实现迭代器(也可能是生成器)的节点模块。 我找不到任何实现。 你可以看看spidermonkey的源代码,并尝试用C ++作为V8的扩展。
您可以尝试以下操作,但是它也会将所有的密钥加载到内存中
Object.keys(o).forEach(function(key) { var val = o[key]; logic(); });
但是由于Object.keys
是一个本地方法,它可能会允许更好的优化。
基准
正如你可以看到Object.keys显着更快。 实际的内存存储是否更加优化是另一回事。
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); });
另外请记住,您可以将.forEach()
函数的第二个parameter passing给指定要用作this
关键字的对象。
// 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);
我是node.js的新手(大约2周),但是我刚刚创build了一个recursion地向控制台报告对象内容的模块。 它将列出全部或search特定项目,然后根据需要向下钻取给定的深度。
也许你可以自定义这个以适应你的需求。 把事情简单化! 为什么复杂?…
'use strict'; //console.log("START: AFutils"); // Recusive console output report of an Object // Use this as AFutils.reportObject(req, "", 1, 3); // To list all items in req object by 3 levels // Use this as AFutils.reportObject(req, "headers", 1, 10); // To find "headers" item and then list by 10 levels // yes, I'm OLD School! I like to see the scope start AND end!!! :-P exports.reportObject = function(obj, key, level, deep) { if (!obj) { return; } var nextLevel = level + 1; var keys, typer, prop; if(key != "") { // requested field keys = key.split(']').join('').split('['); } else { // do for all keys = Object.keys(obj); } var len = keys.length; var add = ""; for(var j = 1; j < level; j++) { // I would normally do {add = add.substr(0, level)} of a precreated multi-tab [add] string here, but Sublime keeps replacing with spaces, even with the ["translate_tabs_to_spaces": false] setting!!! (angry) add += "\t"; } for (var i = 0; i < len; i++) { prop = obj[keys[i]]; if(!prop) { // Don't show / waste of space in console window... //console.log(add + level + ": UNDEFINED [" + keys[i] + "]"); } else { typer = typeof(prop); if(typer == "function") { // Don't bother showing fundtion code... console.log(add + level + ": [" + keys[i] + "] = {" + typer + "}"); } else if(typer == "object") { console.log(add + level + ": [" + keys[i] + "] = {" + typer + "}"); if(nextLevel <= deep) { // drop the key search mechanism if first level item has been found... this.reportObject(prop, "", nextLevel, deep); // Recurse into } } else { // Basic report console.log(add + level + ": [" + keys[i] + "] = {" + typer + "} = " + prop + "."); } } } return ; }; //console.log("END: AFutils");
调整他的代码:
Object.prototype.each = function(iterateFunc) { var counter = 0, keys = Object.keys(this), currentKey, len = keys.length; var that = this; var next = function() { if (counter < len) { currentKey = keys[counter++]; iterateFunc(currentKey, that[currentKey]); next(); } else { that = counter = keys = currentKey = len = next = undefined; } }; next(); }; ({ property1: 'sdsfs', property2: 'chat' }).each(function(key, val) { // do things console.log(key); });