如何通过普通的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的更多反馈:
- caching
Object.keys
或Object.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()方法时变成一个迭代器
在我的情况下(在前面的基础上)是可能的任何级别。
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"]