首页 文章

如何使用对象作为成员遍历纯JavaScript对象?

提问于
浏览
1331

如何遍历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"
    }
}

20 回答

  • 8

    这是AgileJon解决方案的改进和递归版本(demo):

    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);
    

    该解决方案适用于各种不同的深度 .

  • 5

    如果你使用递归,你可以返回任何深度的对象属性 -

    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
    }
    
    */
    
  • 368
    for(var key in validation_messages){
        for(var subkey in validation_messages[key]){
            //code here
            //subkey being value, key being 'yourname' / 'yourmsg'
        }
    }
    
  • 183

    这个问题

    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]);
             }
          }
       }
    }
    
  • 1882

    在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]);
    
    });
    
  • 93
    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]);
        }
    }
    
  • -6

    在ES7中,您可以:

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

    另外一个选项:

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

    对我有用的解决方案如下

    _private.convertParams=function(params){
        var params= [];
        Object.keys(values).forEach(function(key) {
            params.push({"id":key,"option":"Igual","value":params[key].id})
        });
        return params;
    }
    
  • 6

    我认为值得指出的是,jQuery使用 $.each() 很好地排除了这一点 .

    见:https://api.jquery.com/each/

    例如:

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

    $(this) 是对象内的单个项目 . 如果您没有't want to use jQuery'的选择器引擎,请将 $('.foo') 交换为变量 .

  • 3
    var obj={
    name:"SanD",
    age:"27"
    }
    Object.keys(obj).forEach((key)=>console.log(key,obj[key]));
    

    要遍历JavaScript对象,我们可以使用forEach并优化代码,我们可以使用箭头函数

  • 624

    我无法让上述帖子完全按照我的意思去做 .

    在与其他回复一起玩之后,我做了这个 . 这很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
    
  • 27

    这个答案是本文提供的解决方案的集合,包含一些性能反馈 . 我认为有2个用例,OP没有提到他是否需要访问密钥以便在循环过程中使用它们 .

    I.需要访问密钥,

    ✔ the of and Object.keys approach

    let k;
    for (k of Object.keys(obj)) {
    
        /*        k : key
         *   obj[k] : value
         */
    }
    

    ✔ the in approach

    let k;
    for (k in obj) {
    
        /*        k : key
         *   obj[k] : value
         */
    }
    

    谨慎使用这个,因为它可以打印 obj 的原型属性

    ✔ the ES7 approach

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

    但是,在编辑时我不建议使用ES7方法,因为JavaScript在内部初始化了很多变量来构建此过程(请参阅反馈以获取证明) . 除非你没有开发一个值得优化的巨大应用程序,否则它可以,但如果优化是你的首要任务,你应该考虑一下 .

    二 . 我们只需要访问每个值,

    ✔ the of and Object.values approach

    let v;
    for (v of Object.values(obj)) {
    
    }
    

    有关测试的更多反馈:

    • 缓存 Object.keysObject.values 性能可以忽略不计

    例如,

    const keys = Object.keys(obj);
    let i;
    for (i of keys) {
      //
    }
    // same as
    for (i of Object.keys(obj)) {
      //
    }
    
    • 对于 Object.values 情况,在Firefox中使用带有缓存变量的原生 for 循环似乎比使用 for...of 循环要快一些 . 然而,差异并不重要,Chrome运行速度比原始 for 循环快 for...of ,因此我建议在任何情况下处理 Object.values 时使用 for...of (第4和第6次测试) .

    • 在Firefox中, for...in 循环非常慢,因此当我们想要在迭代期间缓存密钥时,最好使用 Object.keys . 此外,Chrome以相同的速度运行两种结构(第一次和最后一次测试) .

    您可以在此处查看测试:https://jsperf.com/es7-and-misc-loops

  • 2

    我知道这已经很晚了,但我花了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]);
                }
    
            }
    
        }
    
    }
    
  • 11

    ES6 中,你可以像这样循环一个对象:(使用arrow function

    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.
    });
    

    以上也可以作为 one-liner

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

    jsbin

    如果您想循环遍历嵌套对象,可以使用 recursive 函数(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.
          {});
    
  • 26

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

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

    使用Underscore.js’s _.each

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

    在我的情况下(基于前面的)可能有任何数量的级别 .

    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"]
    
  • 53

    p是值

    for (var key in p) {
      alert(key + ' => ' + p[key]);
    }
    

    要么

    Object.keys(p).forEach(key => { console.log(key, p[key]) })
    
  • 29
    for(var k in validation_messages) {
        var o = validation_messages[k];
        do_something_with(o.your_name);
        do_something_else_with(o.your_msg);
    }
    

相关问题