遍历对象属性

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个回答

2589
迭代属性需要进行额外的hasOwnProperty检查:
for (var prop in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, prop)) {
        // do stuff
    }
}

这是必要的,因为对象的原型包含了技术上属于该对象的其他属性。这些附加属性是从基本对象类继承而来的,但仍然是obj的属性。

hasOwnProperty只是检查这是否是特定于此类的属性,而不是从基类继承的属性。


也可以通过对象本身调用hasOwnProperty

if (obj.hasOwnProperty(prop)) {
    // do stuff
}

但是,如果对象具有相同名称的不相关字段,则此操作将失败:

var obj = { foo: 42, hasOwnProperty: 'lol' };
obj.hasOwnProperty('foo');  // TypeError: hasOwnProperty is not a function

这就是为什么最好通过Object.prototype进行调用的原因:
var obj = { foo: 42, hasOwnProperty: 'lol' };
Object.prototype.hasOwnProperty.call(obj, 'foo');  // true

26
根据Mozilla文档,如果你只想考虑附加到对象本身的属性,而不是其原型,请使用getOwnPropertyNames或进行hasOwnProperty检查(propertyIsEnumerable也可以使用)。 - davidmdem
7
因为对象的原型包含了与该对象相关的其他属性,这些属性在技术上是该对象的一部分。它们是从基对象类继承来的,但它们仍然是属性。hasOwnProperty方法只是检查该属性是否特定于该类,而不是从基类继承而来。这里有一个很好的解释:http://brianflove.com/2013/09/05/javascripts-hasownproperty-method/ - Kyle Richter
96
不过,我想提一下,现在使用Object.keys(obj)来获取对象键值是更好的解决方案。这是Mozilla文档的链接:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/keys - Kyle Richter
4
我真的不明白这个回答与实际问题有什么关系。除非 OP 修改了 Object.prototype,否则该循环不会显示任何继承属性。这可能是好建议,但你自己说过“我无法理解‘循环遍历对象属性’”。许多人选择不添加 hasOwnProperty 检查。如果你自己创建了对象,并且没有添加一些愚蠢的库来添加属性到 Object.Prototype,那么就不需要进行此类检查。 - Ruan Mendes
9
重要的一条信息缺失了。这里property应当被称为propertyName,因为property是一个字符串。否则会让像我这样的JS新手感到困惑,即不知道在if语句内该做什么。 - Victor Zakharov
显示剩余11条评论

1316

从JavaScript 1.8.5开始,您可以使用Object.keys(obj)来获取在对象本身上定义的属性数组(那些对于obj.hasOwnProperty(key)返回true的属性)。

Object.keys(obj).forEach(function(key,index) {
    // key: the name of the object key
    // index: the ordinal position of the key within the object 
});

使用 Object.keys() 比使用 for-in 循环更好(且更易读)。

以下浏览器支持该方法:

  • Firefox (Gecko): 4 (2.0)
  • Chrome: 5
  • Internet Explorer: 9

有关更多信息,请参阅 Mozilla 开发者网络的 Object.keys() 参考文档


8
这个现在得到了更广泛的支持: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/keys - Dom Vinyard
3
如果您需要支持旧浏览器,可以使用此垫片(polyfill) - KyleMit
27
在支持这种语言结构的环境中,该方法允许调用Array.foreach:Object.keys(myObject).forEach(function(key,index) { //key = 对象键的名称 //index = 键在对象中的序列位置 }); - Todd Price
4
在forEach()中没有很好的方法可以跳出循环。在这种情况下,使用some()函数,并返回true来跳出循环。 - Daniel Z.
16
为什么这个更易读,比起for-in循环?"对于候选人的状态,对于每一个候选人" 这种写法对我来说挺容易读懂的。 - Jona
显示剩余8条评论

380

各位女士和男士,我们已经进入了2019年,没有太多时间来打字......因此让我们使用这个酷炫的新型ECMAScript 2016:

Object.keys(obj).forEach(e => console.log(`key=${e}  value=${obj[e]}`));

23
这与Danny R的回答有何不同? - krillgar
28
这是一条使用map而不是forEach的单行代码。另外,console.log语句可能会引起一些人的兴趣。 - Frank Roth
2
window.performance.memory 仅被 Chrome 支持,而 Object.keys(obj) 返回一个空数组。这与 .map 无关。 - Frank Roth
如果有人不想在单行代码中使用 e 来做多个事情,可以参考我发布的这个 gist。它基本上就像大多数哈希实现一样,使用 ( (key) => (value) ) 而不是 { key => value },但如果你以前没有处理过这种情况,它可能会帮助你更好地理解:https://gist.github.com/the-nose-knows/9f06e745a56ff20519707433e28a4fa8 - kayleeFrye_onDeck
有一个区别:https://dev59.com/hlsW5IYBdhLWcg3w8q5S - Frank Roth
显示剩余3条评论

260

在ES最新版本的实现中,您可以使用Object.entries:

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

或者
Object.entries(obj).forEach(([key, value]) => ...)

如果你仅需要遍历值,则使用Object.values:

for (const value of Object.values(obj)) { }


Object.values(obj).forEach(value => ...)

1
这可能是最好的解决方案(object.entries...),但我不能使用它。当您想要多次执行此操作并且无法在框架中支持它时,可以使用此页面上的polyfill:https://developer.mozilla.org/nl/docs/Web/JavaScript/Reference/Global_Objects/Object/entries - Mario
第三个建议非常棒,如果你只需要属性的值。太棒了! - gnzg
这是最佳答案,你应该使用 for (const [key, value] of Object.entries(obj)) { } - OzzyCzech

228

这是 for...in语句 MDN, ECMAScript规范)。

你可以把它理解为“对于对象 obj 中的每个属性, 将每个属性依次赋值给变量 PROPT ”。


1
非常感谢,我现在明白了。之前我一直在苦思冥想,查阅书籍和谷歌。 - Rafay
21
同意 @RightSaidFred 的观点,in运算符和for语句并不参与其中,for-in语句是一种独立的语法结构:for ( LeftHandSideExpression in Expression )for ( var VariableDeclarationNoIn in Expression ) - Christian C. Salvadó
2
这个答案为什么有这么多赞,尤其是因为这些流行的评论似乎与它相矛盾。 - Doug Molineux
10
为什么这被标记为答案?它很可能是此主题帖中最没有帮助的答案。 - computrius
3
最无用的答案?这要看你认为提问者想问什么;当我第一次读到这个问题时,似乎是对一个变量如何用于检查对象属性的机制感到困惑和不解,而 这个 答案以简洁明了的方式解释了这个问题(尽管“for-in”是一个误称)。我看到的问题“为什么它会列出每个属性”可能暗示着提问者正在寻找 hasOwnProperty,但并不知道它的存在,但我认为更有可能 这个 是提问者想知道的内容,并且错误地接受了一个正确回答了不同问题的答案。 :-) - Bumpy
显示剩余6条评论

44

链接已经失效了 :(。 - Burak
2
@Burak 谢谢你让我知道了 - 已经修复。将来如果有需要,请随时建议修改 :) - Matt Ball

39
if (typeof obj === 'object' && obj !== null) {
    Object.keys(obj).forEach(key => {
        console.log("\n" + key + ": " + obj[key]);
    });
}

// *** Explanation line by line ***

// Explaining the bellow line
// It checks if obj is neither null nor undefined, which means it's safe to get its keys. 
// Otherwise it will give you a "TypeError: Cannot convert undefined or null to object" if obj is null or undefined when it tries to get its keys in the next line of code.
// NOTE 1: You can use Object.hasOwnProperty() instead of Object.keys(obj).length
// NOTE 2: No need to check if obj is an array because it will work just fine.
// NOTE 3: No need to check if obj is a string because it will not pass the 'if typeof obj is Object' statement.
// NOTE 4: No need to check if Obj is undefined because it will not pass the 'if type obj is Object' statement either.
if (typeof obj === 'object' && obj !== null) {

    // Explaining the bellow line
    // Just like in the previous line, this returns an array with
    // all keys in obj (because if code execution got here, it means 
    // obj has keys.) 
    // Then just invoke built-in javascript forEach() to loop
    // over each key in returned array and calls a call back function 
    // on each array element (key), using ES6 arrow function (=>)
    // Or you can just use a normal function ((key) { blah blah }).
    Object.keys(obj).forEach(key => {

        // The bellow line prints out all keys with their 
        // respective value in obj.
        // key comes from the returned array in Object.keys(obj)
        // obj[key] returns the value of key in obj
        console.log("\n" + key + ": " + obj[key]);
    });
}

3
你好,能否添加更多关于你答案的信息呢?仅提供代码是不够的。 - Nicolas
嗨@Nicolas,我已经为代码添加了逐行解释。如果还不清楚,请告诉我。 - Fouad Boukredine
5
由于forEach跳过空值,因此我认为您可以摆脱if语句,只需像Frank Roth的答案一样执行Object.keys(obj).forEach(e => console.log(\key=${e} value=${obj[e]}`));`。 - Darkproduct

31

如果您的环境支持ES2017,我会建议使用Object.entries

Object.entries(obj).forEach(([key, value]) => {
  console.log(`${key} ${value}`);
});

Mozilla的Object.entries()文档所示:

Object.entries()方法返回一个给定对象自身可枚举属性[key, value]对的数组,顺序与使用for...in循环(不同之处在于for-in循环也会枚举原型链中的属性)提供的顺序相同。

简单来说,使用Object.entries我们可以省略使用旧的for...in循环所需的额外步骤:

// This step is not necessary with Object.entries
if (object.hasOwnProperty(property)) {
  // do stuff
}

26

Dominik的答案是完美的,我只是更喜欢这种方式来做,因为它更容易阅读:

for (var property in obj) {
    if (!obj.hasOwnProperty(property)) continue;

    // Do stuff...
}

应该用大写字母O来表示Object,对吧? - Jonathan
1
@Jonathan 注意,第一行中的变量是 object - shrekuu
我已经更新了代码,以避免混淆 ;) - Cyril N.

22

现在,jQuery可以让您做到这一点:

$.each( obj, function( key, value ) {
  alert( key + ": " + value );
});

2
$.each({foo:1, length:0, bar:2}, function(k,v){console.log(k,v)}) $.each不适用于对象。如果一个对象恰好有一个长度属性,而它的值恰好为零,则整个对象将被视为一个空数组。 - Bob Stein
1
我认为这是一种“招致bug”的方法,具体细节请参见此处 - Bob Stein

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