如何遍历或枚举JavaScript对象?


2875

我有一个如下的JavaScript对象:

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

现在我想通过所有回路p元素(p1p2p3 ...),并得到他们的键和值。我怎样才能做到这一点?

我可以根据需要修改JavaScript对象。我的最终目标是遍历一些键值对,如果可能,我想避免使用eval


9
我将JSON更改为JavaScript(对象),以避免混淆对象文字和JSON。
Felix Kling 2012年

Answers:


4362

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

这是代码段:

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

for (var key in p) {
    if (p.hasOwnProperty(key)) {
        console.log(key + " -> " + p[key]);
    }
}

用Object.keys()替代:

var p = {
    0: "value1",
    "b": "value2",
    key: "value3"
};

for (var key of Object.keys(p)) {
    console.log(key + " -> " + p[key])
}

请注意,使用of for-of代替for-in,如果不使用它将在命名属性上返回未定义,并Object.keys()确保仅使用对象自身的属性,而不使用整个原型链属性

使用新Object.entries()方法:

注意: Internet Explorer本身不支持此方法。您可以考虑将Polyfill用于较旧的浏览器。

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

for (let [key, value] of Object.entries(p)) {
  console.log(`${key}: ${value}`);
}

34
建议您将警报行更改为仅为清楚起见alert(key + " -> " + JSON.stringify(p[key]));
Steve Midgley

80
您能解释对hasOwnProperty的需求吗?原型是什么意思?
卡马奇

331
在javascript中,每个对象都有一堆内置的具有元信息的键值对。当您遍历对象的所有键值对时,您也在遍历它们。hasOwnPropery()过滤掉这些。
丹尼尔塔尔斯基

57
实际上,不赞成使用 ......。对于每个...在。但是我真的很喜欢考古学家这个词...我将不得不开始使用它。
本Y

17
javascript中的每个对象(实际上是键值对)都有一个称为__proto__或的属性prototype。此属性对其父对象有引用。对象自动从其父级继承属性。这是使用的原因hasOwnProperty,它表示我们对对象拥有的属性(而不是其父属性)感兴趣。
Zubair Alam 2014年

1102

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

var obj = { first: "John", last: "Doe" };

Object.keys(obj).forEach(function(key) {
    console.log(key, obj[key]);
});

ECMAScript 6添加了for...of

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

ECMAScript 8添加 Object.entries()它,避免了必须在原始对象中查找每个值:

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

您可以合并for...of,解构和Object.entries

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

二者Object.keys()Object.entries()以相同的顺序作为迭代性质for...in但忽略原型链。仅迭代对象自身的可枚举属性。


21
为什么没有提供标准Object.forEach(obj, function (value, key) {...})?:(当然obj.forEach(function...)会更短和补充Array.prototype.forEach,但将风险有对象定义自己的forEach财产,我想,Object.keys对回调警卫修改对象的关键。
大卫·哈克尼斯

7
Object.forEach = function (obj, callback) { Object.keys(obj).forEach(function (key) { callback(obj[key], key); }); }
David Harkness 2014年

7
@DavidHarkness ES2017中有Object.entries。在那里,您可以执行以下操作:Object.entries(obj).map/forEach(([key, value]) => console.log(key, value))([键,值]是数组结构分解,可以直接访问两个项目。并且必须将参数包装在其他括号中。)
Andreas Linnert

如何获取indexjson中的密钥?或者,如果需要,我应该使用一个单独的计数器?
Saravanabalagi Ramachandran

3
for...of是ES6标准,而不是ES2016。
拉克斯·韦伯

341

您必须使用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
}

31
这比levik的解决方案更好,因为它允许主逻辑只能是一个嵌套循环,而不是两个。使代码更易于阅读。尽管我放开了继续的括号;他们是多余的。
SystemicPlural

52
我不会{ }个人删除,因为如果if没有他们,会使您不清楚该部分的内容if,哪些不是。但是我想这只是个意见问题:)
pimvdb 2011年

34
是的,{ }如果以后需要在if示波器上添加一些内容,我倾向于保留主要内容以避免混淆。
Andreas Grech

8
阅读我之前的评论,我意识到我没有使用正确的术语,因为我说的是“如果范围”。但请记住,JavaScript仅具有功能范围。所以我真正的意思是“如果阻止”。
Andreas Grech

1
eomeroff,如果您真的对此感到担心,可以始终执行以下操作: Object.prototype.hasOwnProperty.call(p, prop) 但是,这也无法防止对Object.prototype的操纵...
jordancpaul 2013年

253

如果我们不提及循环对象的替代方法,那么这个问题将是不完整的。

如今,许多知名的JavaScript库都提供了自己的方法来遍历集合,即遍历数组对象类似数组的对象。这些方法使用方便,并且与任何浏览器完全兼容。

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

    $.each(obj, function(key, value) {
        console.log(key, value);
    });
  2. Underscore.js中,您可以找到method _.each(),它对元素列表进行迭代,依次将每个元素依次提供给所提供的函数(请注意iteratee函数中参数的顺序!):

    _.each(obj, function(value, key) {
        console.log(key, value);
    });
  3. Lo-Dash提供了几种遍历对象属性的方法。Basic _.forEach()(或别名_.each())对于循环遍历对象和数组很有用,但是(!)具有length属性的对象被视为数组,并且为避免这种行为,建议使用_.forIn()_.forOwn()方法(这些value参数也要放在最前面):

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

    _.forIn()迭代对象的自身和继承的可枚举属性,而_.forOwn()仅迭代对象的自身属性(基本上检查hasOwnProperty功能)。对于简单的对象和对象文字,这些方法中的任何一种都可以正常工作。

通常,所有描述的方法对于任何提供的对象都具有相同的行为。除了使用本机for..in循环外,通常比其他任何抽象方法都快,例如jQuery.each(),这些方法更易于使用,需要更少的编码并提供更好的错误处理。


4
要获得该值:$ .each(obj,function(key,value){console.log(value.title);});
拉维·拉姆

2
很有趣的是,下划线和jQuery如何更改参数:)
ppasler

52

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

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

下面是我的选择,它是当前版本浏览器(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

对象文字迭代


确实,我只是想发布这种方法。但你击败了我:(
Jamie Hutber 2014年

50

前言:

  • 对象属性可以是自己的(属性在对象本身上),也可以是继承的(不在对象本身上,在其原型之一上)。
  • 对象属性可以是可枚举的不可枚举的。不可枚举的属性被排除在许多属性枚举/数组之外。
  • 属性名称可以是字符串或符号。名称为Symbol的属性被排除在许多属性枚举/数组之外。

在2018年,您可以使用以下选项遍历对象的属性(以下示例如下所示):

  1. for-in[ MDNspec ] —循环结构,循环遍历对象的可枚举属性的名称,包括名称为字符串的继承属性
  2. Object.keys[ MDN规格 ] -提供一个对象的名称的数组的函数自己的枚举的性质,其名称是字符串。
  3. Object.values[ MDN规格 ] -甲函数提供所述的阵列的对象的的自己的枚举的属性。
  4. Object.entries[ MDN规格 ] -提供所述名称的数组的函数一个对象的值自身可枚举属性(阵列中的每个条目是[name, value]阵列)。
  5. Object.getOwnPropertyNames[ MDNspec ] —提供名称为字符串的对象自身属性(甚至是不可枚举的属性)名称数组的函数。
  6. Object.getOwnPropertySymbols[ MDNspec ] —一种函数,提供名称为Symbols 的对象自身属性(甚至是不可枚举的属性)名称的数组。
  7. Reflect.ownKeys[ MDNspec ] —一种函数,提供对象自身属性的名称(甚至是不可枚举的属性)名称的数组,无论这些名称是字符串还是符号。
  8. 如果你想所有对象的属性,包括不可枚举的继承者,你需要使用一个循环,Object.getPrototypeOf[ MDN规格 ]和使用Object.getOwnPropertyNamesObject.getOwnPropertySymbolsReflect.ownKeys在原型链中的每个对象(例如,在此答案的底部)。

随着所有这些硬盘中for-in,你会使用某种类型的阵列上的循环结构(中forfor-offorEach,等)。

例子:

for-in

Object.keys (带有for-of循环,但是您可以使用任何循环构造)

Object.values

Object.entries

Object.getOwnPropertyNames

Object.getOwnPropertySymbols

Reflect.ownKeys

所有属性,包括继承的不可枚举的属性


很好地添加了可枚举/不可枚举的对象属性。
serraosays

49

您可以像这样遍历它:

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

请注意,它key不会采用属性的值,而只是一个索引值。


13
这是重复的,甚至不是完全正确的。您需要检查hasOwnProperty才能使其正常工作
Vatsal 2016年

4
最初,我根据以上评论对它进行了投票,直到我意识到这个答案排在第一位,因此没有“重复”。它可能不完整,但在许多情况下都可以正常工作。
Billynoah '18

27

由于es2015越来越受欢迎,因此我发布了此答案,其中包括使用generator和iterator来平滑地遍历[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页面上找到有关用法的更多信息


这看起来完全是多余的/不需要我的。您是否会将其添加到系统中的每个对象?我以为提供迭代器的目的是,您可以执行“ for(myObject的const [k,v]]”)。看起来好像额外的代码几乎没有提供额外的价值。
Dean Radcliffe

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

注意:您可以在数组上执行此操作,但是也将在length和其他属性上进行迭代。


4
当使用这样的for循环时,key将仅采用一个索引值,这样将仅警告0、1、2等。您需要访问p [key]。
布赖恩

1
它是JavaScript中最慢的数组迭代方法。您可以在计算机上进行检查- 迭代JavaScript中数组的最佳方法
Pencroff 2013年

5
@Pencroff:问题在于问题不在于遍历数组...;)
Sk8erPeter 2014年

这是我在stackoverflow上不了解的内容。理查德给出了正确的答案,他是第一个给出该答案的人,但是他没有得到+1?@Bryan var p = {"p1":"q","p2":"w"}; for(key in p) { alert( key ); }在警报中弹出“ p1”和“ p2”,那怎么了???
塞巴斯蒂安

5
我认为主要的区别在于质量:其他答案不仅说明如何做,而且还说明了警告(例如原型)以及如何处理这些警告。恕我直言,那些其他的答案比我更好:)。
理查德·勒瓦瑟

20

在查看完所有答案之后,我自己的用法不需要​​hasOwnProperty,因为我的json对象是干净的;添加任何额外的javascript处理确实没有任何意义。这就是我正在使用的:

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

18
JSON对象是否干净无关紧要。如果在任何其他时间,某些代码在上设置了属性Object.prototype,则该属性将由枚举for..in。如果确定没有使用任何执行此操作的库,则无需调用hasOwnProperty
G-Wiz 2012年

4
如果使用Object.create(null)
Juan Mendes

20

通过原型的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

2
小心原型:obj = { print: 1, each: 2, word: 3 }产生TypeError: number is not a function。使用forEach相匹配的类似Array功能可能会有所降低风险。
David Harkness 2014年

18

有趣的是,这些答案中的人都涉及到了两个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(检查或不检查.hasOwnProperty()),因为这也有些混乱,因此,除了我上面的回答以外,我在这里要说的是...


您可以使普通对象关联迭代!就像Maps 一样,直接使用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;
    }};
};

无需创建没有精美语法糖的真实Map对象。

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

实际上,使用此填充程序,如果您仍然想利用Map的其他功能(而不是全部填充),但仍想使用整洁的对象表示法,因为对象现在是可迭代的,您现在可以从中制作Map!

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

对于那些不喜欢填充或prototype一般不喜欢的人,可以随意在窗口上创建该函数,getObjIterator()然后调用它。

//no prototype manipulation
function getObjIterator(obj) {
    //create a dummy object instead of adding functionality to all objects
    var iterator = new Object();

    //give it what the shim does but as its own local property
    iterator[Symbol.iterator] = function() {
        var keys = Object.keys(obj)[Symbol.iterator]();
        var output;

        return {next:function() {
            if (!(output = keys.next()).done)
                output.value = [output.value, obj[output.value]];
            return output;
        }};
    };

    return iterator;
}

现在您可以将其作为普通函数调用,其他都不会受到影响

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

要么

for (let pair of getObjIterator(ordinaryObject))

没有理由不起作用。

欢迎来到未来。


1
案例 中的 。只要人们向下滚动并找到帮助,那就很重要。通常情况下,我是在尝试做某件事,而不是喜欢网上看到的东西,最终弄明白了,然后我回来分享。这是一个很好的doco,在谷歌搜索我完全忘记的事情之前,我实际上遇到了自己的答案!
哈什布朗

@HelpMeStackOverflowMyOnlyHope就我个人而言,我不喜欢修改未定义自己的对象的原型。
Janus Troelsen

@JanusTroelsen您是否完整阅读了答案?For those who don't like to shim, or mess with prototype in general, feel free to make the function on window instead, calling it something like getObjIterator() then;
Hashbrown '16

请注意,此技术不适用于普通对象,但仍然有用。
noɥʇʎԀʎzɐɹƆ

它确实适用于普通对象,这实际上是整个问题(以及变量名称,例如ordinaryObject强调魔术仍然适用于这些类型的变量)。你检查演示了吗?什么对你不起作用,@noɥʇʎԀʎzɐɹƆ?(请注意,您的SE个人资料图片是老板)
Hashbrown

13

Object.keys(obj):数组

检索所有可枚举的自己(非继承)属性的所有字符串值的键。

因此,通过使用hasOwnProperty测试每个对象键,它会提供与您期望的键相同的列表。您不需要额外的测试操作,并且Object.keys( obj ).forEach(function( key ){})应该更快。让我们证明一下:

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.");

在我的Firefox中,我得到以下结果

  • Object.keys方法花费了40.21101451665163毫秒。
  • for ... in / hasOwnProperty方法花费了98.26163508463651毫秒。

PS。在Chrome上的差异甚至更大http://codepen.io/dsheiko/pen/JdrqXa

PS2:在ES6(EcmaScript 2015)中,可以更好地迭代可迭代对象:

let map = new Map().set('a', 1).set('b', 2);
for (let pair of map) {
    console.log(pair);
}

// OR 
let map = new Map([
    [false, 'no'],
    [true,  'yes'],
]);
map.forEach((value, key) => {
    console.log(key, value);
});


如果您不想放开{}表示法,则仍可以使用of 而无需创建Maps
Hashbrown

13

这是另一种遍历对象的方法。

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


Object.keys(p).forEach(key => { console.log(key, p[key]) })


3
这非常酷,但是对于大型对象,该for方法可能会更有效。
罗夫(Rolf)'18

13

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

for (var key in p) {
    if (p.hasOwnProperty(key)) {
        console.log(key + " = " + p[key]);
    }
}
<p>
  Output:<br>
  p1 = values1<br>
  p2 = values2<br>
  p3 = values3
</p>


12

您还可以使用Object.keys()并遍历如下所示的对象键来获取值:

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

Object.keys(p).forEach((key)=> {
 console.log(key +' -> '+ p[key]);
});


您节省了我的时间,谢谢
Swap-IOS-Android

很高兴知道:)
Onera

8

仅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
}

8

Object.keys()方法返回给定对象自己的可枚举属性的数组。在这里了解更多

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

Object.keys(p).map((key)=> console.log(key + "->" + p[key]))


8

性能

今天,2020.03.06我在MacOs High Sierra v10.13.6上的Chrome v80.0,Safari v13.0.5和Firefox 73.0.1上执行所选解决方案的测试

结论

  • for-in对于大型和小型对象的所有浏览器,基于(A,B)的解决方案都是快速(或最快)的
  • 出乎意料的是,for-of(H)解决方案可以在铬上快速处理大小物体
  • 基于显式索引i(J,K)的解决方案在所有浏览器中对小对象的响应都非常快(对于Firefox,对于大型对象也是如此,而在其他浏览器中则为中等)
  • 基于迭代器(D,E)的解决方案最慢,不建议使用
  • 解决方案C对于大对象慢,而对小对象慢

在此处输入图片说明

细节

为执行性能测试

  • 小对象-具有3个字段-您可以在计算机上执行测试 此处
  • “大”对象-具有1000个字段-您可以在此处对计算机进行测试

以下摘录介绍了二手解决方案

这是镀铬小物件的结果

在此处输入图片说明


7

您可以向所有对象添加一个简单的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
});

对于那些不喜欢“ -... ”方法的人:

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发生冲突,可以使用唯一的名称来命名。


3
修改内置对象(如Object)的原型通常被认为是一种反模式,因为它很容易引起与其他代码的冲突。所以伤口建议这样做。
莫里兹

6

使用纯JavaScript时,循环可能非常有趣。似乎只有ECMA6(新的2015 JavaScript规范)可以控制循环。不幸的是,在我撰写本文时,浏览器和流行的集成开发环境(IDE)仍在努力完全支持新功能。

乍一看,这是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仅添加了用于数组的方法,该方法基本上创建了一种新的改进方法来遍历数组,同时仍然使旧的冗长而混乱的for循环成为不可迭代的对象。但奇怪的是,这种新forEach方法不支持break,这导致了各种各样的其他问题。

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

截至2015年,我们现在有了更好的开箱即用的方式来循环(和中断)任何对象类型(包括数组和字符串)。当推荐成为主流时,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

在成为新标准之前,仍然可以使用旧方法,但是流行的库中还有其他选择,甚至对于那些不使用这些库的人来说,甚至还有轻量级的选择


你能提供这项工作的小提琴吗?这是我的尝试。jsfiddle.net/abalter/sceeb211
abalter

@abalter对不起,我意识到我的代码中有错字。我已修复它并在此处更新了您的JsFiddle:jsfiddle.net/sceeb211/2
Nicolas Bouvrette

我很迷恋Uncaught TypeError: Object.entries is not a function。尚未在Chrome中实现吗?
abalter

@abalter是的。确保您具有Chrome版本51,并且已按照我的编辑和Jsfiddle注释中的说明启用了该标志。:你可以在这里查看详情developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
萨科Bouvrette

抱歉,我错过了那面旗帜。我看到它还没有完全实现。
abalter

5

在ES6中,我们使用众所周知的符号来公开一些以前的内部方法,您可以使用它来定义迭代器对该对象的工作方式:

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

[...p] //["p1", "p2", "p3"]

这将产生与在es6循环中使用for ...相同的结果。

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

但是了解使用es6现在所具有的功能很重要!


1
一个自定义对象迭代器调用由Object.keys()内存生成并在内存中分配的数组的内置数组迭代器。
ooo,

5

我会这样做,而不是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");
}

5

    var p =[{"username":"ordermanageadmin","user_id":"2","resource_id":"Magento_Sales::actions"},
{"username":"ordermanageadmin_1","user_id":"3","resource_id":"Magento_Sales::actions"}]
for(var value in p) {
    for (var key in value) {
        if (p.hasOwnProperty(key)) {
            console.log(key + " -> " + p[key]);
        }
    }
}


json = [{"key1":"value1","key2":"value2"},{"key1":"value3","key2":"value4"}] for (var i = 0; i < json.length; i++) { for (var key in json[i]) { if (json[i].hasOwnProperty(key)) { console.log(key + " -> " + json[i][key]); } } }
MarekBernád'18


4

如果您还想遍历不可枚举的属性,则可以使用Object.getOwnPropertyNames(obj)返回直接在给定对象上找到的所有属性(无论是否可枚举)的数组。

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/>');
});


2
太好了,谢谢您发布此答案。我需要自检一个Error对象,并且无法在循环或_.forIn(err)调用中获得属性。使用Object.getOwnPropertyNames(err)使我可以访问Error以前无法获得的所有部分。谢谢!
皮尔斯

4

如果有人需要遍历带有条件的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");
      }
   }
}


4

考虑到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 生成器的功能,那么您当然可以使上面的代码更短。

book[Symbol.iterator] = function *(){

  let properties = Object.keys(this);
  for (let p of properties){
    yield this[p];
  }

}

当然,您可以Objectprototype级别可迭代的情况下将此类行为应用于所有对象。

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


我发现代码将生成值,但没有键。是否可以使用键来迭代值?
皮卡

是的你可以。只需返回“ yield [key,obj [key]];”即可。从您的生成器函数中使用,然后像下面的“ for(让{}的{键,值}}}}一样使用它
Artyom Pranovich


4

在最新的ES脚本中,您可以执行以下操作:

let p = {foo: "bar"};
for (let [key, value] of Object.entries(p)) {
  console.log(key, value);
}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.