如何遍历以对象为成员的纯JavaScript对象?

2020/09/16 09:01 · javascript ·  · 0评论

如何遍历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]);
         }
      }
   }
}

ES6 / 2015中,您可以遍历这样的对象:(使用箭头功能

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 / 2016中,您可以使用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.entries(myObj).forEach(([key, val]) => console.log(key, val));

jsbin

如果还想遍历嵌套对象,则可以使用递归函数(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.entries()结合使用Object.fromEntries()ES10 / 2019一次返回一个新对象

const loopNestedObj = obj =>
  Object.fromEntries(
    Object.entries(obj).map(([key, val]) => {
      if (val && typeof val === "object") [key, loopNestedObj(val)]; // recurse
      else [key, updateMyVal(val)]; // or do something with key and val.
    })
  );

使用Underscore.js的_.each

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

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

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
}

*/

该答案是本文中提供的解决方案的汇总,并提供了一些性能反馈我认为有2个用例,OP没有提及他是否需要访问密钥以在循环过程中使用它们。

一,需要访问密钥

ofObject.keys方法

let k;
for (k of Object.keys(obj)) {

    /*        k : key
     *   obj[k] : value
     */
}

in方法

let k;
for (k in obj) {

    /*        k : key
     *   obj[k] : value
     */
}

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

✔ES7方法

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

}

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

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

ofObject.values方法

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.valuesfor在Firefox中使用带有缓存变量的本机循环似乎比使用for...of循环快一点然而不同的是并不重要,并在Chrome运行for...of比本地快for循环,所以我会建议使用for...of与交易时Object.values在任何情况下(第4和第6测试)。

  • 在Firefox中,for...in循环确实很慢,因此当我们要在迭代期间缓存密钥时,最好使用Object.keys另外,Chrome浏览器以相同的速度运行两个结构(第一个和最后一个测试)。

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

我知道这已经很晚了,但是我花了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 k in validation_messages) {
    var o = validation_messages[k];
    do_something_with(o.your_name);
    do_something_else_with(o.your_msg);
}

p是值

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

要么

Object.keys(p).forEach(key => { console.log(key, p[key]) })

在ES7中,您可以执行以下操作:

for (const [key, value] of Object.entries(obj)) {
  //
}
for(var key in validation_messages){
    for(var subkey in validation_messages[key]){
        //code here
        //subkey being value, key being 'yourname' / 'yourmsg'
    }
}

很少有这样做的方法...

1) 2层...在循环中...

for (let key in validation_messages) {
   const vmKeys = validation_messages[key];
   for (let vmKey in vmKeys) {
      console.log(vmKey + vmKeys[vmKey]);
   }
}

2)使用Object.key

Object.keys(validation_messages).forEach(key => {
   const vmKeys = validation_messages[key];
   Object.keys(vmKeys).forEach(key => {
    console.log(vmKeys + vmKeys[key]);
   });
});

3)递归函数

const recursiveObj = obj => {
  for(let key in obj){
    if(!obj.hasOwnProperty(key)) continue;

    if(typeof obj[key] !== 'object'){
      console.log(key + obj[key]);
    } else {
      recursiveObj(obj[key]);
    }
  }
}

并这样称呼:

recursiveObj(validation_messages);

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

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

另外的选择:

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

我认为值得指出的是jQuery很好地解决了这一问题$.each()

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

例如:

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

$(this)是对象中的单个项目。$('.foo')如果不想使用jQuery的选择器引擎,请交换到变量。

ECMAScript-2017(一个月前刚刚完成)引入了Object.values()。现在,您可以执行以下操作:

let v;
for (v of Object.values(validation_messages))
   console.log(v.your_name);   // jimmy billy
var obj={
name:"SanD",
age:"27"
}
Object.keys(obj).forEach((key)=>console.log(key,obj[key]));

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

我无法获得以上职位来做我想做的事情。

在与其他答复一起玩耍之后,我做到了。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

适用于我的解决方案如下

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

异国一号-深度遍历

JSON.stringify(validation_messages,(field,value)=>{
  if(!field) return value;
  
  // ... your code
  
  return value;
})

在此解决方案中,我们使用replacer允许深入遍历整个对象和嵌套对象-在每个级别上,您将获得所有字段和值。如果您需要获取每个字段的完整路径,请点击此处

使用ES8 Object.entries()应该是一种更紧凑的方法来实现此目的。

Object.entries(validation_messages).map(([key,object]) => {

    alert(`Looping through key : ${key}`);

    Object.entries(object).map(([token, value]) => {
        alert(`${token} : ${value}`);
    });
});

2020年,您需要不变的通用功能

这将遍历由子对象,数组和字符串组成的多维对象,并应用自定义函数

export const iterate = (object, func) => {
  const entries = Object.entries(object).map(([key, value]) =>
    Array.isArray(value)
      ? [key, value.map(e => iterate(e, func))]
      : typeof value === 'object'
      ? [key, iterate(value, func)]
      : [key, func(value)]
  );
  return Object.fromEntries(entries);
};

用法:

const r = iterate(data, e=>'converted_'+e);
console.log(r);

就我而言(在前面的基础上)可以是任意数量的级别。

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"]
本文地址:http://javascript.askforanswer.com/ruhebianliyiduixiangweichengyuandechunjavascriptduixiang.html
文章标签:
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!