题 迭代对象属性


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

for(var propt in obj){
    alert(propt + ': ' + obj[propt]);
}

变量怎么样? propt 代表对象的属性?它不是内置方法或属性。那为什么它会提出对象中的每个属性?


1520
2017-11-29 14:30


起源


if (typeof(obj[propt]) === 'object') {/* 再来一遍 */ } - noob
嗯,真的很抱歉这个问题。我知道循环是什么,我无法理解“循环对象属性”,我认为现在已经清除了。此外,他们向我推荐了“JavaScript Step by Step 2nd Edition - Steve Suehring在学校。 - Rafay
这是一个很好的问题。我补充一点,我有15年的其他语言专业经验,我需要这个答案。如果可以的话我会加2000。 - Nathan C. Tresch
很疯狂,但我已经每隔几个月来这个页面多年来重新学习如何做到这一点的语法。我不记得如何做到这一点......我只记得这个页面总是在这里。 - HDave
这是我在StackOverflow上看到的最奇怪的页面。如果你仔细阅读这个问题,那么只有一个答案开始尝试回答实际被问到的问题,并且得分为-6。得分最高的答案被接受,不仅没有答案,而且完全错误。


答案:


迭代属性需要额外的 hasOwnProperty 检查:

for (var property in object) {
    if (object.hasOwnProperty(property)) {
        // do stuff
    }
}

这是必要的,因为对象的原型包含对象的附加属性,这些属性在技术上是对象的一部分。这些附加属性继承自基础对象类,但仍然是属性 object

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


2055
2018-05-24 12:38



@B T根据 Mozilla文档:“如果您只想考虑附加到对象本身的属性,而不是其原型,请使用getOwnPropertyNames 或执行hasOwnProperty检查 (也可以使用propertyIsEnumerable)。“ - davidmdem
究竟是什么叫做 object.hasOwnProperty()?事实并非如此 property 有任何价值意味着它在 object? - Alex S
因为,Alex S,一个对象的原型包含对象的附加属性,这些属性在技术上是对象的一部分。它们是从基础对象类继承的,但它们仍然是属性。 hasOwnProperty只是检查这是否是特定于此类的属性,而不是从基类继承的属性。一个很好的解释: brianflove.com/2013/09/05/javascripts-hasownproperty-method - Kyle Richter
但是,我觉得我应该提一下,Object.keys(obj)现在是获取对象本身密钥的更好解决方案。链接到Mozilla文档: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... - Kyle Richter
缺少一条重要信息。 property 这里是一个字符串,应该被调用 propertyName。否则会对像我这样的JS新手造成混淆,即在内部做什么 if。 - Neolisk


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

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

这比使用for-in循环更好(也更可读)。

它支持这些浏览器:

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

看到 Mozilla开发者网络 Object.keys()的参考 了解更多信息。


775
2017-08-13 07:19



现在,这得到了更广泛的支持: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... - Dom Vinyard
如果您需要支持旧版浏览器,可以使用它 填充工具 - KyleMit
在支持此语言构造的环境中,此方法允许调用Array.foreach: Object.keys(myObject).forEach(function(key,index) { //key = the name of the object key //index = the ordinal position of the key within the object }); - Todd Price
好的解决方案但是如何打破迭代?! - AJ_83
@ AJ_83没有好办法打破forEach()。在这种情况下使用some(),并返回true以中断 - Daniel Ziegler


就是这样 for...in statement (MDNECMAScript规范)。

你可以把它读成“对于 每个财产  该 obj 对象,将每个属性分配给 PROPT 变量依次“。


190
2017-11-29 14:32



同意@RightSaidFred, in 操作员和 for 声明根本不涉及, for-in 声明 代表语法生成: for ( LeftHandSideExpression in Expression ), for ( var VariableDeclarationNoIn in Expression ) - CMS
奇怪的是,这个答案有很多选票,特别是因为这些流行的评论似乎与之相矛盾。 - Doug Molineux
为什么这标志着答案?这个帖子中很可能是最没帮助的.. - computrius
@PeteHerbertPenito,奇怪的是没有人费心去编辑答案,直到 我做到了。 - Dan Dascalescu
最有帮助的答案?取决于你认为OP的要求;当我第一次阅读这个问题时,似乎对于变量可用于检查对象属性的机制感到困惑,以及 这个 答案雄辩地解释(虽然'for-in'用词不当)。问题“为什么它会提出每一个属性”我认为可能意味着OP正在寻找hasOwnProperty但不知道它,但我认为它更有可能 这个 是OP想要知道的,并且错误地接受了对不同问题的正确答案。 :-) - Bumpy


我们在2017年的女孩和男人,我们没有那么多时间打字......所以,让我们这个酷炫的新幻想ECMAScript 2016:

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

144
2017-11-22 08:47



这与Danny R的答案有什么不同? - krillgar
它是一个oneliner并使用map而不是forEach。而且对于某些人来说,console.log语句可能也很有趣。 - Frank Roth
如果您没有直接复制此代码段并想知道为什么您的控制台日志消息被视为字符串,请不要忘记使用反引号(`)而不是单引号(')xD - kayleeFrye_onDeck
如果你想再保存2个字符,你可以摆脱它 () 周围的 e 论据... Object.keys(obj).map(e => console.log(`key=${e} value=${obj[e]}`)) - Grant
forEach 在这里更合适。 map() 当您想要转换数据并使用返回的值时更合适 map()。当你使用 forEach 你是明确的,你只是迭代副作用而不是转换。 - Ski


在即将推出的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 => ...)

58
2017-09-13 06:41



这将是最好的解决方案(object.entries ...),但我无法使用它。如果您想多次执行此操作并且无法在框架中支持它,则可以在此页面上使用polyfill: developer.mozilla.org/nl/docs/Web/JavaScript/Reference/... - Mario
如果你只是属性的值,第三个建议是很好的。真棒! - gnzg


这只是一个 for...in 循环。查看 Mozilla的文档


37
2017-11-29 14:33



这是一个非常基本的区别,而不是本身值得你分配的优点。这是一个写得不好的答案,缺乏对原始问题的背景和应用。 - FlavorScape
这个答案仍然比大多数完全无法解决问题的答案要好得多。 - developerbmw


jquery允许你现在这样做:

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

20
2018-03-29 15:19



$.each({foo:1, length:0, bar:2}, function(k,v){console.log(k,v)}) $ .each是 不合适 对象。如果一个对象碰巧有一个length属性并且它的值恰好为零,则将整个对象视为一个空数组。 - Bob Stein
细节 为什么我认为这是一个 错误邀请方法。 - Bob Stein


上面的答案有点烦人,因为在你确定它是一个对象之后,它们没有解释你在for循环中做了什么:你不直接访问它!实际上,您只交付了需要应用于OBJ的KEY:

var obj = {
  a: "foo",
  b: "bar",
  c: "foobar"
};

// We need to iterate the string keys (not the objects)
for(var someKey in obj)
{
  // We check if this key exists in the obj
  if (obj.hasOwnProperty(someKey))
  {
    // someKey is only the KEY (string)! Use it to get the obj:
    var myActualPropFromObj = obj[someKey]; // Since dynamic, use [] since the key isn't literally named "someKey"

    // NOW you can treat it like an obj
    var shouldBeBar = myActualPropFromObj.b;
  }
}

这都是ECMA5的安全。甚至可以在像Rhino这样的蹩脚JS版本中工作;)


12
2017-10-28 05:39





多米尼克的 答案是完美的,我只是喜欢这样做,因为它更清晰:

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

    // Do stuff...
}

12
2018-01-19 11:03





你可以使用Lodash。 文档 

var obj = {a: 1, b: 2, c: 3};
_.keys(obj).forEach(function (key) {
    ...
});

11
2017-11-04 16:51



为什么这个“答案”有10个赞成?它完全没有回答这个问题。我开始对普通JS开发人员的情报失去信心。 - developerbmw
@developerbmw我明白使用ES6功能是更正确的方法,但我在一年前就回答了。请等一下,请与我们分享您的想法。 - viktarpunko
我们的想法是更多地关注本机方法,而不是建议用户在其页面中添加10000行库。不要误会我的意思,我喜欢使用Lodash但是它有时间和地点,而不是这个。 - Will Hoskings


for ... in循环表示对象中的每个属性,因为它就像for循环一样。您通过执行以下操作在for ... in循环中定义了propt:

    for(var propt in obj){
alert(propt + ': ' + obj[propt]);
}

for ... in循环遍历对象的可枚举属性。无论您定义哪个变量,还是放入for ... in循环,每次变换到它迭代的下一个属性时都会更改。 for ... in循环中的变量遍历键,但它的值是键的值。例如:

    for(var propt in obj) {
      console.log(propt);//logs name
      console.log(obj[propt]);//logs "Simon"
    }

您可以看到变量与变量值的不同之处。相比之下,对于...的循环则相反。

我希望这有帮助。


10
2018-01-24 03:57