迭代对象属性

Raf*_*fay 1904 javascript loops object

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

for(var propt in obj){
    console.log(propt + ': ' + obj[propt]);
}
Run Code Online (Sandbox Code Playgroud)

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

小智 2360

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

for (var prop in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, prop)) {
        // do stuff
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 但是,我觉得我应该提一下,Object.keys(obj)现在是获取对象本身密钥的更好解决方案.链接到Mozilla文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys (85认同)
  • @BT根据[Mozilla文档](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in?redirectlocale=en-US&redirectslug=JavaScript%2FReference% 2FStatements%2Ffor ... in):"如果您只想考虑附加到对象本身的属性,而不是其原型,请使用getOwnPropertyNames**或执行hasOwnProperty检查**(也可以使用propertyIsEnumerable)." (21认同)
  • 缺少一条重要信息.`property`在这里是一个字符串,应该被称为`propertyName`.否则会导致像我这样的JS新手混淆,即在`if`中做什么. (9认同)
  • 因为,Alex S,一个对象的原型包含对象的附加属性,这些属性在技术上是对象的一部分.它们是从基础对象类继承的,但它们仍然是属性.hasOwnProperty只是检查这是否是特定于此类的属性,而不是从基类继承的属性.一个很好的解释:http://brianflove.com/2013/09/05/javascripts-hasownproperty-method/ (5认同)
  • 调用`object.hasOwnProperty()`究竟是什么意思?不是"属性"具有任何价值意味着它在"对象"中的事实吗? (3认同)
  • @Rafay我真的不明白这个答案与实际问题有什么关系.除非OP修改了`Object.prototype`,否则循环不会显示任何继承的属性.这可能是一个很好的建议,但你自己说"我无法理解"循环对象属性"`.许多人选择不添加`hasOwnProperty`检查.如果您自己创建了该对象,并且没有添加一些将属性添加到`Object.Prototype`的哑库,则不需要进行此类检查. (3认同)
  • 这根本不回答这个问题.为什么有1700人投票呢? (3认同)
  • if('javascript'.hasOwnProperty(0))console.log('好吧,你真的只是搞砸了我,不是吗,javascript?'); (2认同)
  • 这个答案需要针对“ES7”进行更新,使用诸如“Object.entries”和“Object.values”之类的方法。 (2认同)

Dan*_*y R 1074

从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 
});
Run Code Online (Sandbox Code Playgroud)

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

它支持这些浏览器:

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

有关更多信息,请参阅Mozilla Developer Network Object.keys()的参考.

  • 在支持此语言构造的环境中,此方法允许调用Array.foreach:`Object.keys(myObject).forEach(function(key,index){// key =对象键的名称// index =对象内的键的顺序位置});` (27认同)
  • 为什么这比for-in更具可读性?`候选人状态中的候选人......似乎对我来说可读 (11认同)
  • 现在支持得更广泛:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys (7认同)
  • @ AJ_83没有好办法打破forEach().在这种情况下使用some(),并返回true以中断 (4认同)
  • 如果您需要支持旧浏览器,可以使用此[polyfill](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys#Polyfill) (3认同)
  • 好的解决方案 但是如何打破迭代?! (2认同)
  • 请注意,使用“Object.keys”会更改键的顺序并对它们进行排序,因此如果您关心对象中项目的顺序,则应该使用接受的答案 (2认同)
  • 令我惊讶的是,任何人都会发现这种语法“更具可读性”。我想这完全取决于你的背景,但对我来说很难击败 for(loop control here) { do stuff here } 语法。自从 StackExchange 上的大多数人出生之前,这种结构就已经出现在各种语言中。javascript 结构,以函数调用作为参数,从整体上看是相当新的。 (2认同)

Fra*_*oth 273

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

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

  • `forEach`在这里更合适.当你想要转换数据并使用`map()`返回的值时,`map()`更合适.当你使用`forEach`时,你明确表示你只是迭代副作用而不是转换. (33认同)
  • 它是一个oneliner并使用map而不是forEach.而且对于某些人来说,console.log语句可能也很有趣. (22认同)
  • 这与Danny R的答案有什么不同? (12认同)
  • 当一个更加语义正确的函数`forEach`可用时,你为什么要使用`map`? (7认同)
  • 如果你想再保存2个字符,你可以摆脱`e`参数周围的`()`...```Object.keys(obj).map(e => console.log(`key = $ {e} value = $ {obj [e]}`))``` (5认同)
  • 如果你没有直接复制这个片段,并想知道为什么你的控制台日志消息被视为一个字符串,不要忘记使用反引号(`)而不是单引号(')xD (4认同)
  • `window.performance.memory`仅受chrome支持,而`Object.keys(obj)`返回一个空数组.这与`.map`无关. (2认同)

Mar*_*c B 210

这是for...in statement(MDN,ECMAScript规范).

你可以把它读作" FOR每个属性INobj对象,每个属性分配给PROPT依次变量".

  • 同意@RightSaidFred,`in`运算符和`for`语句根本不涉及,[`for-in`语句](http://es5.github.com/#x12.6.4)表示语法单独生成:`for(表达式中的LeftHandSideExpression)`,`for(表达式中的var VariableDeclarationNoIn)` (21认同)
  • 为什么这标志着答案?这可能是这个帖子中最没帮助的一个.. (9认同)
  • 最有帮助的答案?取决于你认为OP的要求; 当我第一次阅读这个问题时,似乎对于变量可用于检查对象属性的机制感到困惑,而且这个答案雄辩地解释了(尽管有"for-in"用词不当).问题"为什么它提出了每一个属性"我认为OP可能意味着OP正在寻找hasOwnProperty但不知道它,但我认为它更可能是_this_是OP想要知道的,并且错误地接受了正确的回答另一个问题.:-) (3认同)
  • 奇怪的是,这个答案有很多选票,特别是因为这些流行的评论似乎与之相矛盾. (2认同)

小智 121

在即将推出的ES版本中,您可以使用Object.entries:

for (const [key, value] of Object.entries(obj)) { }
Run Code Online (Sandbox Code Playgroud)

要么

Object.entries(obj).forEach(([key, value]) => ...)
Run Code Online (Sandbox Code Playgroud)

如果您只想迭代值,则使用Object.values:

for (const value of Object.values(obj)) { }
Run Code Online (Sandbox Code Playgroud)

要么

Object.values(obj).forEach(value => ...)
Run Code Online (Sandbox Code Playgroud)


Mat*_*all 37

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

  • 这是一个非常基本的区别,而不是本身值得你分配的优点.这是一个写得不好的答案,缺乏对原始问题的背景和应用. (20认同)
  • @Burak 感谢您让我知道 - 已修复。将来,请随时提出修改建议:) (2认同)

Fou*_*ine 30

if(Object.keys(obj).length) {
    Object.keys(obj).forEach(key => {
        console.log("\n" + key + ": " + obj[key]);
    });
}

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

// Explaining the bellow line
// It checks if obj has at least one property. Here is how:
// Object.keys(obj) will return an array with all keys in obj.
// Keys are just the regular incremental numbers starting from 0.
// If there is no keys in obj, it will return empty array = []
// Then it will get its length. At this point, it checks: 
// If it has at least one element, it means it's bigger than 0 
// which evaluates to true and the bellow code will be executed.
// Else means it's length = 0 which evaluates to false
// NOTE: you can use Object.hasOwnProperty() instead of Object.keys(obj).length
if(Object.keys(obj).length) {

    // 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]);
    });
}
Run Code Online (Sandbox Code Playgroud)

  • 因为 `forEach` [跳过空值](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach),我认为你可以摆脱 if 和 just像 Frank Roth 的回答一样,执行 `Object.keys(obj).forEach(e => console.log(\`key=${e} value=${obj[e]}\`));` 。 (5认同)
  • 您好,您能否添加有关您答案的更多信息,仅提供代码没有帮助。 (3认同)

JSO*_*C11 24

如果您的环境支持ES2017,那么我会推荐Object.entries:

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

Mozillas Object.entries()文档中所示:

所述Object.entries()方法返回在给定对象的自己的可枚举的属性[键,值]对的数组,在相同的顺序,通过提供一种用于... in循环(不同之处在于一个用于-in循环枚举原型链中的属性也是如此).

基本上使用Object.entries,我们可以放弃以下额外的步骤,这对于旧的for ... in循环是必需的:

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


Rob*_*ick 21

jquery允许你现在这样做:

$.each( obj, function( key, value ) {
  alert( key + ": " + value );
});
Run Code Online (Sandbox Code Playgroud)

  • `$.each({foo:1, length:0, bar:2}, function(k,v){console.log(k,v)})` $.each [不适合](https:// github.com/jquery/jquery/issues/3588#issuecomment-288682581) 用于对象。如果一个对象碰巧有一个 length 属性并且它的值碰巧为零,则整个对象被视为一个空数组。 (2认同)

Cyr*_* N. 20

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

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

    // Do stuff...
}
Run Code Online (Sandbox Code Playgroud)


dyl*_*724 18

上面的答案有点烦人,因为在你确定它是一个对象之后,它们没有解释你在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;
  }
}
Run Code Online (Sandbox Code Playgroud)

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


Dim*_*ski 15

添加ES2015的用法,Reflect.ownKeys(obj)并通过迭代器迭代属性.

例如:

let obj = { a: 'Carrot', b: 'Potato', Car: { doors: 4 } };
Run Code Online (Sandbox Code Playgroud)

可以迭代

// logs each key
Reflect.ownKeys(obj).forEach(key => console.log(key));
Run Code Online (Sandbox Code Playgroud)

如果您想直接迭代对象键的值,您可以定义一个iterator,就像JavaScipts的字符串,数组,类型数组,Map和Set的默认迭代器一样.

JS将尝试通过默认迭代器属性进行迭代,该属性必须定义为Symbol.iterator.

如果您希望能够迭代所有对象,可以将其添加为Object的原型:

Object.prototype[Symbol.iterator] = function*() { 
    for(p of Reflect.ownKeys(this)){ yield this[p]; }
}
Run Code Online (Sandbox Code Playgroud)

这将使您能够使用for ... of循环迭代对象的值,例如:

for(val of obj) { console.log('Value is:' + val ) }
Run Code Online (Sandbox Code Playgroud)

注意:截至编写此答案(2018年6月)所有其他浏览器,但IE,支持生成器和for...of迭代通过Symbol.iterator


Sun*_*nny 13

您可以使用for...inandforEach循环访问对象的嵌套属性。

对于...在:

for (const key in info) {
    console.log(info[key]);
}
Run Code Online (Sandbox Code Playgroud)

为每个:

Object.keys(info).forEach(function(prop) {
    console.log(info[prop]);
    // cities: Array[3], continent: "North America", images: Array[3], name: "Canada"
    // "prop" is the property name
    // "data[prop]" is the property value
});
Run Code Online (Sandbox Code Playgroud)


小智 11

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

    for(var propt in obj){
alert(propt + ': ' + obj[propt]);
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

我希望这有帮助.


Phi*_*l_t 11

let obj = {"a": 3, "b": 2, "6": "a"}

Object.keys(obj).map((item) => {console.log("item", obj[item])})

// a
// 3
// 2
Run Code Online (Sandbox Code Playgroud)

  • 正如其他评论中提到的,`forEach` 在这里更合适,因为 `map` 旨在返回一个新数组,其中包含每次迭代调用代码块的结果。但是我们只对每次迭代的副作用感兴趣,而不是返回值,因此我们不需要 `map` 给我们的新数组。 (2认同)

小智 10

你可以使用Lodash.文档

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

  • 为什么这个"回答"有10个赞成?它完全没有回答这个问题.我开始对普通JS开发人员的情报失去信心. (10认同)

Fel*_*ger 10

Object.keys(obj).forEach(key =>
  console.log(`key=${key} value=${obj[key]}`)
);
Run Code Online (Sandbox Code Playgroud)


arb*_*arb 9

您的for循环正在迭代对象的所有属性obj.propt在for循环的第一行中定义.它是一个字符串,是obj对象属性的名称.在循环的第一次迭代中,propt将是"名称".


小智 9

JavaScript中的对象是属性的集合,因此可以在每个语句的循环中循环.

您应该将其obj视为关键值集合.


Red*_*edu 9

现在,您可以通过添加Symbol.iterator方法将标准JS对象转换为可迭代对象.然后你可以使用for of循环并直接加入它的值,甚至也可以在对象上使用扩展运算符.凉.让我们看看我们如何做到:

var o = {a:1,b:2,c:3},
    a = [];
o[Symbol.iterator] = function*(){
                       var ok = Object.keys(this);
                            i = 0;
                       while (i < ok.length) yield this[ok[i++]];
                     };
for (var value of o) console.log(value);
// or you can even do like
a = [...o];
console.log(a);
Run Code Online (Sandbox Code Playgroud)


akh*_*hid 8

在JavaScript中迭代对象的方式类型

  • 对于...在循环

  • for ... of循环

  • forEach() 方法

  • map()方法

let obj = {
  city1: 'BOM',
  city2: 'BLR',
  city3: 'HYD',
  state: {
    city1: 'Sub-city1',
    city2: 'Sub-city2'
  }
}
console.log('----------------using for...in loop------')
for(let entry in obj) 
  console.log(entry +" -> "+ obj[entry])

for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
        console.log(key + " -> " + obj[key]);
    }
}
console.log('----------------using for...of loop------')
for (const key of Object.keys(obj)) 
    console.log(key +" -> "+ obj[key]);

for (const [key, value] of Object.entries(obj)) 
    console.log(key +" -> "+ value);

console.log('----------------using forEach loop------')
Object.entries(obj).forEach(([key, value]) => console.log(key +" -> "+ value));
    
console.log('----------------using map function------')
Object.entries(obj).map(([k,v])=> console.log(k+' -> '+v))
Run Code Online (Sandbox Code Playgroud)

嵌套对象的迭代方法

let obj = {
  city1: 'ALD',
  city2: 'BLR',
  city3: 'HYD',
  state: {
    city4: 'Sub-city1',
    city5: 'Sub-city2'
  }
}
function nestedObj(obj) {
    for (let key in obj) {
        // checking if it's nested to iterate again
        if (obj.hasOwnProperty(key) && 
           (typeof obj[key] === "object")) {
            nestedObj(obj[key])
        } else {
            // showing the flat attributes
            console.log(key + " -> " + obj[key]);
        }
    }
}
nestedObj(obj);
Run Code Online (Sandbox Code Playgroud)


Jad*_*mas 5

我想补充上面的答案,因为你可能有与 Javascript 不同的意图。JSON 对象和 Javascript 对象是不同的东西,您可能想要使用上面提出的解决方案迭代 JSON 对象的属性,然后会感到惊讶。

假设您有一个 JSON 对象,例如:

var example = {
    "prop1": "value1",
    "prop2": [ "value2_0", "value2_1"],
    "prop3": {
         "prop3_1": "value3_1"
    }
}
Run Code Online (Sandbox Code Playgroud)

迭代其“属性”的错误方法:

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

当迭代和的属性时,您可能会惊讶地看到控制台日志记录0、等。这些对象是序列,序列的索引是 Javascript 中该对象的属性。1prop1prop2prop3_1

递归迭代 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]);

            }
            
     }
}
Run Code Online (Sandbox Code Playgroud)


Jus*_*tin 5

如果运行节点,我建议:

Object.keys(obj).forEach((key, index) => {
    console.log(key);
});
Run Code Online (Sandbox Code Playgroud)


iRo*_*tia 5

虽然最受好评的答案是正确的,但这是一个替代用例,即如果您要遍历一个对象并想最后创建一个数组。使用.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]
})
Run Code Online (Sandbox Code Playgroud)