如何循环或枚举JavaScript对象?

我有一个JavaScript对象,如下所示:

var p = { "p1": "value1", "p2": "value2", "p3": "value3" }; 

现在我想遍历所有p元素( p1p2p3 …)并获得它们的键和值。 我怎样才能做到这一点?

如有必要,我可以修改JavaScript对象。 我的最终目标是循环通过一些关键值对,如果可能的话,我想避免使用eval

您可以使用其他人所示的for-in循环。 但是,您还必须确保所获得的密钥是对象的实际属性,而不是来自原型。

这里是片段:

 var p = { "p1": "value1", "p2": "value2", "p3": "value3" }; for (var key in p) { if (p.hasOwnProperty(key)) { console.log(key + " -> " + p[key]); } } 

在ECMAScript 5下,可以结合Object.keys()Array.prototype.forEach()

 var obj = { first: "John", last: "Doe" }; Object.keys(obj).forEach(function(key) { console.log(key, obj[key]); }); 

ES2016增加for...of

 for (const key of Object.keys(obj)) { console.log(key, obj[key]); } 

ES2017增加了Object.entries() ,避免了在原始对象中查找每个值:

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

Object.keys()Object.entries()以与for...in循环相同的顺序迭代属性, 但忽略原型链 。 只有对象自己的枚举属性被迭代。

你必须使用for-in循环

但是在使用这种循环时要非常小心,因为这样会循环原型链中的所有属性

因此,在使用for-in循环时,请始终使用hasOwnProperty方法来确定迭代中的当前属性是否是您正在检查的对象的属性:

 for (var prop in p) { if (!p.hasOwnProperty(prop)) { //The current property is not a direct property of p continue; } //Do your logic with the property here } 

如果我们没有提到循环对象的替代方法,这个问题就不会完整。

现在,许多知名的JavaScript库提供了自己的迭代集合的方法,即通过数组对象类似数组的对象 。 这些方法使用方便,并且完全兼容任何浏览器。

  1. 如果你使用jQuery ,你可以使用jQuery.each()方法。 它可以用来无缝遍历对象和数组:

     $.each(obj, function(key, value) { console.log(key, value); }); 
  2. _.each() ,你可以find方法_.each() ,它遍历元素列表,每个依次产生一个提供的函数(注意iteratee函数中参数的顺序!):

     _.each(obj, function(value, key) { console.log(key, value); }); 
  3. Lo-Dash提供了几种迭代对象属性的方法。 基本的_.forEach() (或者它的别名_.each() )对循环对象和数组非常有用,但是具有length属性的(!)对象像数组一样对待,为了避免这种行为,build议使用_.forIn()_.forOwn()方法(这些方法也value参数):

     _.forIn(obj, function(value, key) { console.log(key, value); }); 

    _.forIn()遍历一个对象的自己和inheritance的可枚举属性,而_.forOwn()仅遍历一个对象的自身属性(基本上检查hasOwnProperty函数)。 对于简单的对象和对象文字,任何这些方法都可以正常工作。

通常,所有描述的方法与任何提供的对象具有相同的行为。 除了使用本地for..in循环通常比任何抽象如jQuery.each() 更快 ,这些方法相当容易使用,需要更less的编码,并提供更好的error handling。

在ECMAScript 5中,您可以在文字Object.keys迭代字段中使用新的方法

您可以在MDN上看到更多信息

我的select是作为一个更快的解决scheme在当前版本的浏览器(Chrome30,IE10,FF25)

 var keys = Object.keys(p), len = keys.length, i = 0, prop, value; while (i < len) { prop = keys[i]; value = p[prop]; i += 1; } 

您可以将此方法的性能与jsperf.com上的不同实现进行比较 :

  • 扩展实现
  • 对象键迭代
  • 对象字面迭代

浏览器支持你可以在Kangax的compat表上看到

对于旧的浏览器,你有简单和充分的 polyfill

UPD:

性能比较在perfjs.info这个问题上的所有最stream行的案例:

对象字面迭代

你可以像遍历它一样:

 for (var key in p) { alert(p[key]); } 

请注意, key不会取得属性的值,它只是一个索引值。

通过原型forEach()应该跳过原型链属性:

 Object.prototype.each = function(f) { var obj = this Object.keys(obj).forEach( function(key) { f( key , obj[key] ) }); } //print all keys and values var obj = {a:1,b:2,c:3} obj.each(function(key,value) { console.log(key + " " + value) }); // a 1 // b 2 // c 3 

在查看这里的所有答案后,hasOwnProperty不是我自己用法所必需的,因为我的json对象是干净的; 添加任何额外的JavaScript处理真的没有意义。 这是我正在使用的所有:

 for (var key in p) { console.log(key + ' => ' + p[key]); // key is key // value is p[key] } 

Object.keys(obj):Array

检索所有可枚举自己(非inheritance)属性的所有string值的键。

因此,通过使用hasOwnPropertytesting每个对象键,它可以提供相同的键列表。 你不需要额外的testing操作, Object.keys( obj ).forEach(function( key ){})应该会更快。 我们来certificate一下:

 var uniqid = function(){ var text = "", i = 0, possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; for( ; i < 32; i++ ) { text += possible.charAt( Math.floor( Math.random() * possible.length ) ); } return text; }, CYCLES = 100000, obj = {}, p1, p2, p3, key; // Populate object with random properties Array.apply( null, Array( CYCLES ) ).forEach(function(){ obj[ uniqid() ] = new Date() }); // Approach #1 p1 = performance.now(); Object.keys( obj ).forEach(function( key ){ var waste = obj[ key ]; }); p2 = performance.now(); console.log( "Object.keys approach took " + (p2 - p1) + " milliseconds."); // Approach #2 for( key in obj ) { if ( obj.hasOwnProperty( key ) ) { var waste = obj[ key ]; } } p3 = performance.now(); console.log( "for...in/hasOwnProperty approach took " + (p3 - p2) + " milliseconds."); 

由于es2015越来越受欢迎,我发布了这个答案,其中包括生成器和迭代器的使用顺利迭代[key, value]对。 因为在Ruby等其他语言中是可能的。

好的,这里是一个代码:

 const MyObject = { 'a': 'Hello', 'b': 'it\'s', 'c': 'me', 'd': 'you', 'e': 'looking', 'f': 'for', [Symbol.iterator]: function* () { for (const i of Object.keys(this)) { yield [i, this[i]]; } } }; for (const [k, v] of MyObject) { console.log(`Here is key ${k} and here is value ${v}`); } 

所有关于如何在开发人员Mozilla页面上执行迭代器和生成器的信息。

希望它帮助了一个人。

编辑:

ES2017将包含Object.entries ,它将使对象中的[key, value]对迭代更加容易。 现在已知它将是根据TS39阶段信息的一个标准的一部分。

我认为是时候更新我的答案,让它变得比现在更新鲜。

 const MyObject = { 'a': 'Hello', 'b': 'it\'s', 'c': 'me', 'd': 'you', 'e': 'looking', 'f': 'for', }; for (const [k, v] of Object.entries(MyObject)) { console.log(`Here is key ${k} and here is value ${v}`); } 

您可以在MDN页面find更多关于使用情况的信息

在这些答案中有趣的人已经触及Object.keys()for...of但是从未将它们合并:

 var map = {well:'hello', there:'!'}; for (let key of Object.keys(map)) console.log(key + ':' + map[key]); 

你不能只for...of一个Object因为它不是一个迭代器, for...index.forEach()Object.keys()是丑陋的/低效率的。
我很高兴大多数人不会for...in (不pipe是否检查.hasOwnProperty() ),因为这也有点混乱,所以除了我上面的回答,我在这里说…


你可以使普通的对象关联迭代! performance就像Map s直接使用幻想for...of
在Chrome和FF中使用DEMO (我只假设ES6)

 var ordinaryObject = {well:'hello', there:'!'}; for (let pair of ordinaryObject) //key:value console.log(pair[0] + ':' + pair[1]); //or for (let [key, value] of ordinaryObject) console.log(key + ':' + value); 

只要你在下面包括我的垫片:

 //makes all objects iterable just like Maps!!! YAY //iterates over Object.keys() (which already ignores prototype chain for us) Object.prototype[Symbol.iterator] = function() { var keys = Object.keys(this)[Symbol.iterator](); var obj = this; var output; return {next:function() { if (!(output = keys.next()).done) output.value = [output.value, obj[output.value]]; return output; }}; }; 

而不必创build一个真正的Map对象,它没有很好的语法糖。

 var trueMap = new Map([['well', 'hello'], ['there', '!']]); for (let pair of trueMap) console.log(pair[0] + ':' + pair[1]); 

事实上,如果你仍然想利用Map的其他function(而不是将它们全部填满),但是仍然希望使用整齐的对象符号,因为对象现在可以迭代了,现在可以从中创build一个Map!

 //shown in demo var realMap = new Map({well:'hello', there:'!'}); 

对于那些不喜欢的人来说,或者不喜欢一般的prototype ,可以自由地在窗口上做这个函数,然后像getObjIterator()那样调用它。

 var realMap = new Map(getObjIterator({well:'hello', there:'!'})) 

要么

 for (let pair of getObjIterator(ordinaryObject)) 

没有理由不这样做。

欢迎来到未来

 var p = { "p1": "value1", "p2": "value2", "p3": "value3" }; for (var key in p) { if (p.hasOwnProperty(key)) { alert(key + " = " + p[key]); } } --------------------------- --------------------------- Output: p1 = values1 p2 = values2 p3 = values3 
 for(key in p) { alert( p[key] ); } 

注意:你可以通过数组来完成这个任务,但是你也可以迭代length和其他属性。

您可以将一个简单的forEach函数添加到所有对象,以便您可以自动遍历任何对象:

 Object.defineProperty(Object.prototype, 'forEach', { value: function (func) { for (var key in this) { if (!this.hasOwnProperty(key)) { // skip loop if the property is from prototype continue; } var value = this[key]; func(key, value); } }, enumerable: false }); 

对于那些不喜欢“ for … in ”的人来说 – 方法:

 Object.defineProperty(Object.prototype, 'forEach', { value: function (func) { var arr = Object.keys(this); for (var i = 0; i < arr.length; i++) { var key = arr[i]; func(key, this[key]); } }, enumerable: false }); 

现在,你可以简单的调用:

 p.forEach (function(key, value){ console.log ("Key: " + key); console.log ("Value: " + value); }); 

如果您不想与其他forEach-Methods发生冲突,则可以用您的唯一名称命名。

我会这样做,而不是检查每一个obj.hasOwnerProperty for ... in循环。

 var obj = {a : 1}; for(var key in obj){ //obj.hasOwnProperty(key) is not needed. console.log(key); } //then check if anybody has messed the native object. Put this code at the end of the page. for(var key in Object){ throw new Error("Please don't extend the native object"); } 

如果你想迭代不可枚举的属性 ,你可以使用Object.getOwnPropertyNames(obj)来返回直接在给定对象上find的所有属性(可枚举或不可枚举)的数组。

 var obj = Object.create({}, { // non-enumerable property getFoo: { value: function() { return this.foo; }, enumerable: false } }); obj.foo = 1; // enumerable property Object.getOwnPropertyNames(obj).forEach(function (name) { document.write(name + ': ' + obj[name] + '<br/>'); }); 

只有没有依赖关系的JavaScript代码:

 var p = {"p1": "value1", "p2": "value2", "p3": "value3"}; keys = Object.keys(p); // ["p1", "p2", "p3"] for(i = 0; i < keys.length; i++){ console.log(keys[i] + "=" + p[keys[i]]); // p1=value1, p2=value2, p3=value3 } 

使用纯JavaScript时,循环可能会非常有趣。 看来,只有ECMA6(2015年新的JavaScript规范)得到了控制的循环。 不幸的是,在我写这篇文章的时候,浏览器和stream行的集成开发环境(IDE)仍然在努力完全支持新的function。

一眼就可以看出ECMA6之前的JavaScript对象循环:

 for (var key in object) { if (p.hasOwnProperty(key)) { var value = object[key]; console.log(key); // This is the key; console.log(value); // This is the value; } } 

此外,我知道这是超出了这个问题的范围,但在2011年,ECMAScript 5.1增加了forEach方法的数组,只是基本上创build了一个新的改进的方式来循环通过数组,同时仍然留下不可迭代的对象与旧的详细和令人困惑for循环。 但奇怪的是,这个新的forEach方法不支持导致各种其他问题的break

基本上在2011年,除了许多stream行的库(jQuery,Underscore等)决定重新实现之外,还没有真正可靠的JavaScript循环方法。

截至2015年,我们现在有更好的开箱即用的方式来循环(和中断)任何对象types(包括数组和string)。 下面是当推荐成为主stream时,JavaScript中的一个循环最终会是什么样子的:

 for (let [key, value] of Object.entries(object)) { console.log(key); // This is the key; console.log(value); // This is the value; } 

请注意,截至2016年6月18日,大多数浏览器将不支持上述代码。即使在Chrome中,您也需要启用此特殊标志才能运行: chrome://flags/#enable-javascript-harmony

直到这成为新的标准,旧的方法仍然可以使用,但也有stream行的图书馆的替代品,甚至没有使用任何这些图书馆的轻量级替代品 。

考虑到ES6我想添加我自己的勺糖,并提供一个更多的方法来迭代对象的属性。

由于普通的JS对象不能迭代 ,所以我们无法使用for..of循环遍历其内容。 但是没有人能阻止我们使其迭代

让我们有book对象。

 let book = { title: "Amazing book", author: "Me", pages: 3 } book[Symbol.iterator] = function(){ let properties = Object.keys(this); // returns an array with property names let counter = 0; let isDone = false; let next = () => { if(counter >= properties.length){ isDone = true; } return { done: isDone, value: this[properties[counter++]] } } return { next }; } 

既然我们已经做到了,我们可以这样使用它:

 for(let pValue of book){ console.log(pValue); } ------------------------ Amazing book Me 3 

或者如果您知道ES6 生成器的function ,那么您肯定可以使代码更短。

 book[Symbol.iterator] = function *(){ let properties = Object.keys(this); for (let p of properties){ yield this[p]; } } 

当然,您可以将所有对象的这种行为应用于prototype级别的Object迭代。

 Object.prototype[Symbol.iterator] = function() {...} 

此外,符合可迭代协议的对象可以与新的ES2015特征扩展运算符一起使用,因此我们可以将对象属性值作为数组读取。

 let pValues = [...book]; console.log(pValues); ------------------------- ["Amazing book", "Me", 3] 

或者你可以使用解构赋值:

 let [title, , pages] = book; // notice that we can just skip unnecessary values console.log(title); console.log(pages); ------------------ Amazing book 3 

你可以用上面提供的所有代码检查JSFiddle

如果有人需要通过arrayObjects循环条件

 var arrayObjects = [{"building":"A", "status":"good"},{"building":"B","status":"horrible"}]; for (var i=0; i< arrayObjects.length; i++) { console.log(arrayObjects[i]); for(key in arrayObjects[i]) { if (key == "status" && arrayObjects[i][key] == "good") { console.log(key + "->" + arrayObjects[i][key]); }else{ console.log("nothing found"); } } } 

在ES6中我们有一些众所周知的符号来公开一些以前的内部方法,你可以用它来定义这个对象的迭代器是如何工作的:

 var p = { "p1": "value1", "p2": "value2", "p3": "value3", *[Symbol.iterator]() { yield *Object.keys(this); } }; [...p] //["p1", "p2", "p3"] 

这将给出与在es6循环中使用…相同的结果。

 for(var key in p) { console.log(key); } 

但重要的是知道你现在使用es6的function!

一个对象在实现.next()方法时变成一个迭代器

 const james = { name: 'James', height: `5'10"`, weight: 185, [Symbol.iterator]() { let properties = [] for (let key of Object.keys(james)){ properties.push(key); } index = 0; return { next: () => { let key = properties[index]; let value = this[key]; let done = index >= properties.length - 1 ; index++; return { key, value, done }; } }; } }; const iterator = james[Symbol.iterator](); console.log(iterator.next().value); // 'James' console.log(iterator.next().value); // `5'10` console.log(iterator.next().value); // 185 

由于ES2015可以使用for循环,直接访问元素:

 // before ES2015 for(var key of elements){ console.log(elements[key]); } // ES2015 for(let element of elements){ console.log(element); } 

希望这有助于某人。

使用Angular时遇到了类似的问题,下面是我find的解决scheme。

第1步。获取所有的对象键。 使用Object.keys。 这个方法返回一个给定对象自己可枚举属性的数组。

第2步。创build一个空数组。 这是一个所有属性都将生存的地方,因为你的新的ngFor循环将指向这个数组,所以我们必须把它们全部抓住。 第3步。迭代抛出所有的键,并推动每一个你创build的数组。 这是代码中的样子。

  // Evil response in a variable. Here are all my vehicles. let evilResponse = { "car" : { "color" : "red", "model" : "2013" }, "motorcycle": { "color" : "red", "model" : "2016" }, "bicycle": { "color" : "red", "model" : "2011" } } // Step 1. Get all the object keys. let evilResponseProps = Object.keys(evilResponse); // Step 2. Create an empty array. let goodResponse = []; // Step 3. Iterate throw all keys. for (prop of evilResponseProps) { goodResponse.push(evilResponseProps[prop]); } 

这是原始post的链接。 https://medium.com/@papaponmx/looping-over-object-properties-with-ngfor-in-angular-869cd7b2ddcc

除了提问者(' 最终目标是循环一些关键值对 ')并最终不寻找循环。

 var p ={"p1":"value1","p2":"value2","p3":"value3"}; if('p1' in p){ var val=p['p1']; ... }