如何通过普通的JavaScript对象与作为成员的对象循环?

我如何循环JavaScript对象中的所有成员,包括对象的值。

例如,我怎么可以循环访问(每个访问“your_name”和“your_message”)?

var validation_messages = { "key_1": { "your_name": "jimmy", "your_msg": "hello world" }, "key_2": { "your_name": "billy", "your_msg": "foo equals bar" } } 
 for (var key in validation_messages) { // skip loop if the property is from prototype if (!validation_messages.hasOwnProperty(key)) continue; var obj = validation_messages[key]; for (var prop in obj) { // skip loop if the property is from prototype if(!obj.hasOwnProperty(prop)) continue; // your code alert(prop + " = " + obj[prop]); } } 

在ECMAScript 5下,可以结合Object.keys()Array.prototype.forEach()

 var obj = { first: "John", last: "Doe" }; // // Visit non-inherited enumerable keys // Object.keys(obj).forEach(function(key) { console.log(key, obj[key]); }); 

这个问题

 for (var key in validation_messages) { var obj = validation_messages[key]; for (var prop in obj) { alert(prop + " = " + obj[prop]); } } 

你也会循环通过原始对象的原型。

有了这个,你会避免它:

 for (var key in validation_messages) { if (validation_messages.hasOwnProperty(key)) { var obj = validation_messages[key]; for (var prop in obj) { if (obj.hasOwnProperty(prop)) { alert(prop + " = " + obj[prop]); } } } } 

使用_.each_.each

 _.each(validation_messages, function(value, key){ _.each(value, function(value, key){ console.log(value); }); }); 

ES6中,你可以像这样循环一个对象:(使用箭头函数 )

 Object.keys(myObj).forEach(key => { console.log(key); // the name of the current key. console.log(myObj[key]); // the value of the current key. }); 

jsbin

ES7中,您可以使用Object.entries而不是Object.keys并像这样循环对象:

 Object.entries(myObj).forEach(([key, val]) => { console.log(key); // the name of the current key. console.log(val); // the value of the current key. }); 

以上内容也可以作为单行使用

 Object.keys(myObj).forEach(key => console.log(key, myObj[key])); 

jsbin

如果你想循环嵌套对象,你可以使用recursion函数(ES6):

 const loopNestedObj = (obj) => { Object.keys(obj).forEach(key => { if (obj[key] && typeof obj[key] === 'object') loopNestedObj(obj[key]); // recurse. else console.log(key, obj[key]); // or do something with key and val. }); }; 

jsbin

与上面的函数相同,但使用ES7 Object.entries而不是Object.keys

 const loopNestedObj = (obj) => { Object.entries(obj).forEach(([key, val]) => { if (val && typeof val === 'object') loopNestedObj(val); // recurse. else console.log(key, val); // or do something with key and val. }); }; 

如果你正在进行函数式编程,你可以使用Object.keys / Object.entries枚举对象,然后处理这些值,然后使用reduce()将其转换回新的对象。

 const loopNestedObj = (obj) => Object.keys(obj) // Use .filter(), .map(), etc. if you need. .reduce((newObj, key) => (obj[key] && typeof obj[key] === 'object') ? {...newObj, [key]: loopNestedObj(obj[key])} : // recurse. {...newObj, [key]: obj[key]}, // Define value. {}); 

如果使用recursion,则可以返回任何深度的对象属性 –

 function lookdeep(object){ var collection= [], index= 0, next, item; for(item in object){ if(object.hasOwnProperty(item)){ next= object[item]; if(typeof next== 'object' && next!= null){ collection[index++]= item + ':{ '+ lookdeep(next).join(', ')+'}'; } else collection[index++]= [item+':'+String(next)]; } } return collection; } //example var O={ a:1, b:2, c:{ c1:3, c2:4, c3:{ t:true, f:false } }, d:11 }; var lookdeepSample= 'O={'+ lookdeep(O).join(',\n')+'}'; /* returned value: (String) O={ a:1, b:2, c:{ c1:3, c2:4, c3:{ t:true, f:false } }, d:11 } */ 
 for(var k in validation_messages) { var o = validation_messages[k]; do_something_with(o.your_name); do_something_else_with(o.your_msg); } 

我知道这很晚了,但是花了2分钟的时间写出这个优化和改进版本的AgileJon的答案:

 var key, obj, prop, owns = Object.prototype.hasOwnProperty; for (key in validation_messages ) { if (owns.call(validation_messages, key)) { obj = validation_messages[key]; for (prop in obj ) { // using obj.hasOwnProperty might cause you headache if there is // obj.hasOwnProperty = function(){return false;} // but owns will always work if (owns.call(obj, prop)) { console.log(prop, "=", obj[prop]); } } } } 
 for(var key in validation_messages){ for(var subkey in validation_messages[key]){ //code here //subkey being value, key being 'yourname' / 'yourmsg' } } 

在ES7中,你可以这样做:

 for (const [key, value] of Object.entries(obj)) { // } 

AgileJon解决scheme( 演示版 )的改进和recursion版本如下:

 function loopThrough(obj){ for(var key in obj){ // skip loop if the property is from prototype if(!obj.hasOwnProperty(key)) continue; if(typeof obj[key] !== 'object'){ //your code console.log(key+" = "+obj[key]); } else { loopThrough(obj[key]); } } } loopThrough(validation_messages); 

该解决scheme适用于各种不同的深度。

另一种select:

 var testObj = {test: true, test1: false}; for(let x of Object.keys(testObj)){ console.log(x); } 

我认为值得指出的是,jQuery用$.each()很好地sorting。

请参阅: https : //api.jquery.com/each/

例如:

 $('.foo').each(function() { console.log($(this)); }); 

$(this)是对象内的单个项目。 如果您不想使用jQuery的select器引擎,请将$('.foo')交换$('.foo')一个variables。

ECMAScript-2017,刚刚在一个月前完成,引入了Object.values()。 所以,现在你可以做到这一点:

 let v; for (v of Object.values(validation_messages)) console.log(v.your_name); // jimmy billy 

这个答案是通过一些性能反馈提供给这个问题的综合解决scheme。 我想有2个用例,OP没有提到他是否需要caching迭代期间使用的密钥。

1.如果密钥需要caching,

我们可以使用Object.keys ,例如:

 let k; for (k of Object.keys(obj)) { // now 'obj[k]' refers to the value and 'k' to the key; } 

使用ES7

@KévinBerthommier提供了这个ES7解决scheme:

 for (const [key, value] of Object.entries(obj)) { // } 

不过,除非你只有一小部分数据来处理,否则我不build议使用这种方法。 这个方法看起来很整洁,但是如果我们看看性能反馈(包括Firefox和Chrome),执行时间真的很慢,因为JavaScript在内部初始化了很多variables来构build这个结构。

2.如果我们只想访问每个值,

我们可以使用Object.values ,例如:

 let v; for (v of Object.values(obj)) { // now 'v' refers to the value in the iteration } 

有关testing的更多反馈:

  • cachingObject.keysObject.values性能可以忽略不计

例如,

 const keys = Object.keys(obj); let i; for (i in keys) { // } // same as for (i in Object.keys(obj)) { // } 
  • 对于Object.values情况,在Firefox中使用带有cachingvariables的本地for循环似乎比使用for...of循环快一点。 然而,差异不是那么重要,Chrome运行for...of速度比原生的for循环更快,所以我build议在任何情况下(第4和第6次testing)处理Object.values时使用for...of

  • 在Firefox中, for...in循环非常慢,所以当我们想在迭代过程中caching键时,最好使用Object.keys 。 Plus Chrome同时运行两种结构(第一次和最后一次testing)。

你可以在这里检查testing: https : //jsperf.com/es7-and-misc-loops

我无法得到以上的post,做了我以后的事情。

在这里玩了其他回复后,我做了这个。 这是hacky,但它的作品!

对于这个对象:

 var myObj = { pageURL : "BLAH", emailBox : {model:"emailAddress", selector:"#emailAddress"}, passwordBox: {model:"password" , selector:"#password"} }; 

…这个代码:

 // Get every value in the object into a separate array item ... function buildArray(p_MainObj, p_Name) { var variableList = []; var thisVar = ""; var thisYes = false; for (var key in p_MainObj) { thisVar = p_Name + "." + key; thisYes = false; if (p_MainObj.hasOwnProperty(key)) { var obj = p_MainObj[key]; for (var prop in obj) { var myregex = /^[0-9]*$/; if (myregex.exec(prop) != prop) { thisYes = true; variableList.push({item:thisVar + "." + prop,value:obj[prop]}); } } if ( ! thisYes ) variableList.push({item:thisVar,value:obj}); } } return variableList; } // Get the object items into a simple array ... var objectItems = buildArray(myObj, "myObj"); // Now use them / test them etc... as you need to! for (var x=0; x < objectItems.length; ++x) { console.log(objectItems[x].item + " = " + objectItems[x].value); } 

…在控制台中生成这个:

 myObj.pageURL = BLAH myObj.emailBox.model = emailAddress myObj.emailBox.selector = #emailAddress myObj.passwordBox.model = password myObj.passwordBox.selector = #password 

一个对象在实现.next()方法时变成一个迭代器

https://stackoverflow.com/a/47268581/6204133

在我的情况下(在前面的基础上)是可能的任何级别。

 var myObj = { rrr: undefined, pageURL : "BLAH", emailBox : {model:"emailAddress", selector:"#emailAddress"}, passwordBox: {model:"password" , selector:"#password"}, proba: {odin:{dva:"rr",trr:"tyuuu"}, od:{ff:5,ppa:{ooo:{lll:'lll'}},tyt:'12345'}} }; function lookdeep(obj,p_Name,gg){ var A=[], tem, wrem=[], dd=gg?wrem:A; for(var p in obj){ var y1=gg?'':p_Name, y1=y1 + '.' + p; if(obj.hasOwnProperty(p)){ var tem=obj[p]; if(tem && typeof tem=='object'){ a1=arguments.callee(tem,p_Name,true); if(a1 && typeof a1=='object'){for(i in a1){dd.push(y1 + a1[i])};} } else{ dd.push(y1 + ':' + String(tem)); } } }; return dd }; var s=lookdeep(myObj,'myObj',false); for (var x=0; x < s.length; ++x) { console.log(s[x]+'\n');} 

结果:

 ["myObj.rrr:undefined", "myObj.pageURL:BLAH", "myObj.emailBox.model:emailAddress", "myObj.emailBox.selector:#emailAddress", "myObj.passwordBox.model:password", "myObj.passwordBox.selector:#password", "myObj.proba.odin.dva:rr", "myObj.proba.odin.trr:tyuuu", "myObj.proba.od.ff:5", "myObj.proba.od.ppa.ooo.lll:lll", "myObj.proba.od.tyt:12345"]