遍历对象属性

2354

var obj = {
    name: "Simon",
    age: "20",
    clothing: {
        style: "simple",
        hipster: false
    }
}

for(var propt in obj){
    console.log(propt + ': ' + obj[propt]);
}

< p>变量propt如何表示对象的属性?它不是内置方法或属性。为什么它出现在对象的每个属性中?< /p>

15
如果(typeof(obj [propt])=== 'object'){ /再做一次/ } - noob
13
非常抱歉问这个问题。我知道什么是循环,但我无法理解“循环遍历对象属性”,现在我已经明白了。他们还向我推荐了在学校使用的《JavaScript逐步学习第二版-Steve Suehring》。 - Rafay
276
这是一个不错的初学者问题。我想补充一下,虽然我有15年其他语言的专业经验,但我仍需要这个答案。如果可以的话,我会加上2000分。 - Nathan C. Tresch
74
有点疯狂,但我已经几年来每隔几个月就会来这个页面重新学习如何使用语法。我不费心去记忆怎么做... 我只记得这个页面总是在SO上可用。 - Dave
19
这是我在StackOverflow上看过最奇怪的页面。如果你仔细阅读问题,只有一个答案甚至开始尝试回答实际被问的问题,它得分为-6分。最高得分的答案被接受了,但不仅没有回答问题,而且完全是错误的。 - user1106925
显示剩余3条评论
32个回答

7

如果您正在运行Node,我建议:

Object.keys(obj).forEach((key, index) => {
    console.log(key);
});

6

尽管顶级答案是正确的,但这里有一个备用用例,即如果您正在迭代对象并想在最后创建数组。 使用.map而不是forEach

const newObj = Object.keys(obj).map(el => {
    //ell will hold keys 
   // Getting the value of the keys should be as simple as obj[el]
})

5
我希望在上面的答案中添加一些内容,因为你可能有不同于Javascript的意图。 JSON对象和Javascript对象是不同的东西,你可能想使用上面提出的解决方案遍历JSON对象的属性,然后会感到惊讶。
假设你有一个像这样的JSON对象:
var example = {
    "prop1": "value1",
    "prop2": [ "value2_0", "value2_1"],
    "prop3": {
         "prop3_1": "value3_1"
    }
}

迭代 'properties' 的错误方式:

function recursivelyIterateProperties(jsonObject) {
    for (var prop in Object.keys(example)) {
        console.log(prop);
        recursivelyIterateProperties(jsonObject[prop]);
    }
}

您可能会感到惊讶,当迭代prop1prop2prop3_1的属性时,在控制台记录了01等。这些对象是序列,而序列的索引在Javascript中是该对象的属性。
更好的一种递归遍历JSON对象属性的方法是先检查该对象是否为序列:
function recursivelyIterateProperties(jsonObject) {
    for (var prop in Object.keys(example)) {
        console.log(prop);
        if (!(typeof(jsonObject[prop]) === 'string')
            && !(jsonObject[prop] instanceof Array)) {
                recursivelyIterateProperties(jsonObject[prop]);

            }
            
     }
}

4
此外,还可以采用递归的方式来实现:
function iterate(obj) {
    // watch for objects we've already iterated so we won't end in endless cycle
    // for cases like var foo = {}; foo.bar = foo; iterate(foo);
    var walked = [];
    var stack = [{obj: obj, stack: ''}];
    while(stack.length > 0)
    {
        var item = stack.pop();
        var obj = item.obj;
        for (var property in obj) {
            if (obj.hasOwnProperty(property)) {
                if (typeof obj[property] == "object") {
                  // check if we haven't iterated through the reference yet
                  var alreadyFound = false;
                  for(var i = 0; i < walked.length; i++)
                  {
                    if (walked[i] === obj[property])
                    {
                      alreadyFound = true;
                      break;
                    }
                  }
                  // new object reference
                  if (!alreadyFound)
                  {
                    walked.push(obj[property]);
                    stack.push({obj: obj[property], stack: item.stack + '.' + property});
                  }
                }
                else
                {
                    console.log(item.stack + '.' + property + "=" + obj[property]);
                }
            }
        }
    }
}

使用方法:

iterate({ foo: "foo", bar: { foo: "foo"} }); 

1
@faiz - 请看我的评论,这是为了防止你在递归遍历具有循环引用的对象时陷入无限循环的保障措施。 - Ondrej Svejdar

4

for...in循环的作用是创建一个新变量(var someVariable),并将给定对象的每个属性依次存储在这个新变量(someVariable)中。因此,如果使用代码块 {},可以进行迭代。请考虑以下示例。

var obj = {
     name:'raman',
     hobby:'coding',
     planet:'earth'
     };

for(var someVariable in obj) {
  //do nothing..
}

console.log(someVariable); // outputs planet

点赞这个,因为它很简单。在我的用例中,我需要检查对象中的所有属性是否有不良值- NaN、null、undefined(它们是图表上的点,这些值会阻止图表绘制)。为了获取值而不是名称,在循环中你只需执行 obj[someVariable]。也许它被踩得那么多的原因是因为它不是递归的。所以如果你有一个高度结构化的对象,这不是一个足够好的解决方案。 - Katharine Osborne
@KatharineOsborne 或许是因为以下短语有点神秘:“因此,如果您使用 block {},则可以进行迭代。” 代码比文本更能说明问题。 - bvdb

4

在这里,我正在遍历每个节点并创建有意义的节点名称。如果你注意到,instanceOf Array和instanceOf Object基本上做相同的事情(在我的应用程序中,我提供了不同的逻辑)。

function iterate(obj,parent_node) {
    parent_node = parent_node || '';
    for (var property in obj) {
        if (obj.hasOwnProperty(property)) {
            var node = parent_node + "/" + property;
            if(obj[property] instanceof Array) {
                //console.log('array: ' + node + ":" + obj[property]);
                iterate(obj[property],node)
            } else if(obj[property] instanceof Object){
                //console.log('Object: ' + node + ":" + obj[property]);
                iterate(obj[property],node)
            }
            else {
                console.log(node + ":" + obj[property]);
            }
        }
    }
}

注意 - 我受到了Ondrej Svejdar答案的启发,但这个解决方案性能更好,且不那么含糊。


4
你基本上想要循环遍历对象中的每个属性。 JSFiddle
var Dictionary = {
  If: {
    you: {
      can: '',
      make: ''
    },
    sense: ''
  },
  of: {
    the: {
      sentence: {
        it: '',
        worked: ''
      }
    }
  }
};

function Iterate(obj) {
  for (prop in obj) {
    if (obj.hasOwnProperty(prop) && isNaN(prop)) {
      console.log(prop + ': ' + obj[prop]);
      Iterate(obj[prop]);
    }
  }
}
Iterate(Dictionary);

1

检查类型

您可以通过以下方式检查属性如何表示对象属性:

typeof propt

发现它只是一个字符串(属性名称)。这是由于for-in js“内置”循环的工作方式导致对象中的每个属性都会出现。

var obj = {
    name: "Simon",
    age: "20",
    clothing: {
        style: "simple",
        hipster: false
    }
}

for(var propt in obj){
    console.log(typeof propt,  propt + ': ' + obj[propt]);
}


1
进一步完善接受的答案值得注意的是,如果您使用var object = Object.create(null)实例化对象,则object.hasOwnProperty(property)将触发TypeError。因此为了安全起见,您需要像这样从原型调用它:
for (var property in object) {
    if (Object.prototype.hasOwnProperty.call(object, property)) {
        // do stuff
    }
}

0

如果您只想迭代映射属性值,那么 Lodash 有 _.mapValues

const obj = {
  a: 2,
  b: 3
}
const res = _.mapValues(obj, v => v * 2)
console.log(res)
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接