如何循环或枚举JavaScript对象?

Tan*_*moy 2704 javascript each loops

我有一个像以下JavaScript对象:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};
Run Code Online (Sandbox Code Playgroud)

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

如有必要,我可以修改JavaScript对象.我的最终目标是遍历一些键值对,如果可能的话,我想避免使用eval.

lev*_*vik 4161

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

这是片段:

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

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

  • 在javascript中,每个对象都有一堆具有元信息的内置键值对.循环遍历对象的所有键值对时,也会循环遍历它们.hasOwnPropery()过滤掉这些. (317认同)
  • 你能解释一下hasOwnProperty的必要性吗?你的原型是什么意思? (75认同)
  • 实际上,不推荐使用[For ... in](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in).[对于每个......](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for_each ...因素)是.但我真的很喜欢_考古学家_...我将不得不开始使用它. (55认同)
  • 建议您更改警报线,只是为了清除`alert(key +" - >"+ JSON.stringify(p [key])); (31认同)
  • javascript中的每个对象(实际上是一个键值对)都有一个名为`__proto__`或`prototype`的属性.此属性具有对其父对象的引用.对象自动从其父级继承属性.这就是使用`hasOwnProperty`的原因,它表示我们对对象拥有的属性感兴趣而不是它的父属. (14认同)
  • For..in很丑陋,容易出错并且已弃用(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for_each...in).除非您必须使用IE8或更低版本支持考古学家,否则请使用Object.keys(). (11认同)
  • 不要使用`obj.hasOwnProperty(prop)`进行成员资格检查.使用`Object.prototype.hasOwnProperty.call(obj,prop)`代替,即使"set"包含值"hasOwnProperty"`也可以.资料来源:http://stackoverflow.com/questions/7958292/mimicking-sets-in-javascript#comment25623359_7958422 (6认同)
  • "不幸的是,hasOwnProperty是一个方法,而不是一个操作符,因此在任何对象中它都可以被替换为不同的函数,甚至是一个不是函数的值" (4认同)
  • 对于任何关心性能的人来说,“for..in”+“hasOwnProperty”在正常使用中会稍微快一些(https://jsben.ch/pCDAk),而“Object.keys”则比几千个属性要快得多(https://jsben.ch/pCDAk) ://jsben.ch/ptzsL)。 (2认同)

Axe*_*yer 1025

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

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

Object.keys(obj).forEach(function(key) {
    console.log(key, obj[key]);
});
Run Code Online (Sandbox Code Playgroud)

ECMAScript 6补充说for...of:

for (const key of Object.keys(obj)) {
    console.log(key, obj[key]);
}
Run Code Online (Sandbox Code Playgroud)

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

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

for...ofObject.entries迭代特性以相同的次序作为Object.keys()但忽略原型链.只迭代对象自己的可枚举属性.

  • 为什么标准没有提供`Object.forEach(obj,function(value,key){...})`?:(当然`obj.forEach(function ...)`会更短并且补充`Array.prototype.forEach`,但这会冒对象定义自己的`forEach`属性.我想`Object.keys`可以防范修改对象键的回调. (21认同)
  • `Object.forEach = function (obj, callback) { Object.keys(obj).forEach(function (key) { callback(obj[key], key); }); }` (6认同)
  • @DavidHarkness ES2017中有Object.entries.你可以在那里执行以下操作:`Object.entries(obj).map/forEach(([key,value])=> console.log(key,value))`([key,value]是数组解构,访问两个项目直接.你必须将参数包装在额外的parens.) (6认同)
  • `for ... of`是ES6标准,而不是ES2016. (3认同)
  • Python太简单了,javascript我每次都要查基础知识。 (3认同)

And*_*ech 334

你必须使用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
}
Run Code Online (Sandbox Code Playgroud)

  • 我不会亲自删除`{}`,因为没有它们的`if`会让我们有点不清楚`if`和什么不是.但我想这只是意见问题:) (51认同)
  • 是的,我更喜欢保持`{}`主要是为了避免混淆,如果后来需要在`if`范围添加内容. (33认同)
  • 这比levik的解决方案更好,因为它允许主逻辑只有一个嵌套循环,而不是两个; 使代码更容易阅读.虽然我松开了继续周围的括号; 它们是多余的. (30认同)
  • 阅读我之前的评论,我意识到我没有使用正确的术语,因为我说"如果范围"; 但请记住,JavaScript只有函数范围.所以我实际上的意思是"if block". (8认同)

Vis*_*ioN 250

如果我们不提及循环对象的替代方法,那么问题就不会完整.

如今,许多众所周知的JavaScript库提供了自己的迭代集合的方法,即在数组,对象类似数组的对象上.这些方法使用方便,并且与任何浏览器完全兼容.

  1. 如果您使用jQuery,您可以使用jQuery.each()方法.它可用于无缝迭代对象和数组:

    $.each(obj, function(key, value) {
        console.log(key, value);
    });
    
    Run Code Online (Sandbox Code Playgroud)
  2. Underscore.js中,你可以找到方法_.each(),它迭代一个元素列表,然后依次产生一个提供的函数(注意iteratee函数中参数的顺序!):

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

    _.forIn(obj, function(value, key) {
        console.log(key, value);
    });
    
    Run Code Online (Sandbox Code Playgroud)

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

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

  • 获取值:$ .each(obj,function(key,value){console.log(value.title);}); (4认同)
  • 只是有趣的下划线和jquery如何改变参数:) (2认同)

Pen*_*off 49

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

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

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

对于旧浏览器,您有简单完整的 polyfill

UPD:

此问题中所有最常见案例的性能比较perfjs.info:

对象文字迭代


Bry*_*yan 48

您可以像以下一样迭代它:

for (var key in p) {
  alert(p[key]);
}
Run Code Online (Sandbox Code Playgroud)

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

  • 这是重复的,甚至不完全正确.您需要检查hasOwnProperty才能使其正常工作 (13认同)
  • 我最初基于上述评论对此进行了下调,直到我意识到这个答案是第一位的,因此不会"重复".它可能是不完整的,但对许多情况来说效果很好. (4认同)

T.J*_*der 43

前言:

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

在2018年,您循环访问对象属性的选项是:

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

与他们的不同之处Reflect.ownKeys,你会使用某种类型的循环结构的阵列上的(for-in,for,for-of等).

例子:

forEach:

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const name in o) {
    const value = o[name];
    console.log(`${name} = ${value}`);
}
Run Code Online (Sandbox Code Playgroud)

for-in (使用Object.keys循环,但您可以使用任何循环结构):

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const name of Object.keys(o)) {
    const value = o[name];
    console.log(`${name} = ${value}`);
}
Run Code Online (Sandbox Code Playgroud)

for-of:

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const value of Object.values(o)) {
    console.log(`${value}`);
}
Run Code Online (Sandbox Code Playgroud)

Object.values:

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const [name, value] of Object.entries(o)) {
    console.log(`${name} = ${value}`);
}
Run Code Online (Sandbox Code Playgroud)

Object.entries:

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const name of Object.getOwnPropertyNames(o)) {
    const value = o[name];
    console.log(`${name} = ${value}`);
}
Run Code Online (Sandbox Code Playgroud)

Object.getOwnPropertyNames:

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const name of Object.getOwnPropertySymbols(o)) {
    const value = o[name];
    console.log(`${String(name)} = ${value}`);
}
Run Code Online (Sandbox Code Playgroud)

Object.getOwnPropertySymbols:

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const name of Reflect.ownKeys(o)) {
    const value = o[name];
    console.log(`${String(name)} = ${value}`);
}
Run Code Online (Sandbox Code Playgroud)

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

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (let depth = 0, current = o; current; ++depth, current = Object.getPrototypeOf(current)) {
    for (const name of Reflect.ownKeys(current)) {
        const value = o[name];
        console.log(`[${depth}] ${String(name)} = ${String(value)}`);
    }
}
Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper {
  max-height: 100% !important;
}
Run Code Online (Sandbox Code Playgroud)


Kam*_*ski 28

表现

今天 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) 解决方案在 chrome 上对于小物体和大物体都很快
  • 基于显式索引i(J,K) 的解决方案在所有浏览器上对于小对象都非常快(对于 firefox 对大对象也很快,但在其他浏览器上速度中等)
  • 基于迭代器 (D,E) 的解决方案最慢,不推荐
  • 解决方案 C 对大物体慢,对小物体中等慢

在此处输入图片说明

细节

进行了性能测试

  • 小对象 - 有 3 个字段 - 您可以在这里在您的机器上执行测试
  • “大”对象 - 有 1000 个字段 - 您可以在您的机器上执行测试这里

下面的片段展示了使用过的解决方案

function A(obj,s='') {
	for (let key in obj) if (obj.hasOwnProperty(key)) s+=key+'->'+obj[key] + ' ';
  return s;
}

function B(obj,s='') {
	for (let key in obj) s+=key+'->'+obj[key] + ' ';
  return s;
}

function C(obj,s='') {
  const map = new Map(Object.entries(obj));
	for (let [key,value] of map) s+=key+'->'+value + ' ';
  return s;
}

function D(obj,s='') {
  let o = { 
    ...obj,
    *[Symbol.iterator]() {
      for (const i of Object.keys(this)) yield [i, this[i]];    
    }
  }
  for (let [key,value] of o) s+=key+'->'+value + ' ';
  return s;
}

function E(obj,s='') {
  let o = { 
    ...obj,
    *[Symbol.iterator]() {yield *Object.keys(this)}
  }
  for (let key of o) s+=key+'->'+o[key] + ' ';
  return s;
}

function F(obj,s='') {
	for (let key of Object.keys(obj)) s+=key+'->'+obj[key]+' ';
  return s;
}

function G(obj,s='') {
	for (let [key, value] of Object.entries(obj)) s+=key+'->'+value+' ';
  return s;
}

function H(obj,s='') {
	for (let key of Object.getOwnPropertyNames(obj)) s+=key+'->'+obj[key]+' ';
  return s;
}

function I(obj,s='') {
	for (const key of Reflect.ownKeys(obj)) s+=key+'->'+obj[key]+' ';
  return s;
}

function J(obj,s='') {
  let keys = Object.keys(obj);
	for(let i = 0; i < keys.length; i++){
    let key = keys[i];
    s+=key+'->'+obj[key]+' ';
  }
  return s;
}

function K(obj,s='') {
  var keys = Object.keys(obj), len = keys.length, i = 0;
  while (i < len) {
    let key = keys[i];
    s+=key+'->'+obj[key]+' ';
    i += 1;
  }
  return s;
}

function L(obj,s='') {
  Object.keys(obj).forEach(key=> s+=key+'->'+obj[key]+' ' );
  return s;
}

function M(obj,s='') {
  Object.entries(obj).forEach(([key, value]) => s+=key+'->'+value+' ');
  return s;
}

function N(obj,s='') {
  Object.getOwnPropertyNames(obj).forEach(key => s+=key+'->'+obj[key]+' ');
  return s;
}

function O(obj,s='') {
  Reflect.ownKeys(obj).forEach(key=> s+=key+'->'+obj[key]+' ' );
  return s;
}



// TEST

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};
let log = (name,f) => console.log(`${name} ${f(p)}`)

log('A',A);
log('B',B);
log('C',C);
log('D',D);
log('E',E);
log('F',F);
log('G',G);
log('H',H);
log('I',I);
log('J',J);
log('K',K);
log('L',L);
log('M',M);
log('N',N);
log('O',O);
Run Code Online (Sandbox Code Playgroud)
This snippet only presents choosen solutions
Run Code Online (Sandbox Code Playgroud)

这是镀铬小物体的结果

在此处输入图片说明


Fie*_*Cod 26

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

有关如何在开发人员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}`);
}
Run Code Online (Sandbox Code Playgroud)

您可以在MDN页面上找到有关使用的更多信息


Akh*_*ani 26

单行和更具可读性的代码可以是..

Object.entries(myObject).map(([key, value]) => console.log(key, value))
Run Code Online (Sandbox Code Playgroud)


Ric*_*eur 21

for(key in p) {
  alert( p[key] );
}
Run Code Online (Sandbox Code Playgroud)

注意:您可以在数组上执行此操作,但您也将遍历length其他属性.

  • @Pencroff:问题是问题不是关于循环数组...;) (5认同)
  • 我认为主要区别在于质量:其他答案不仅告诉我们如何,而且还要告诉警告(例如原型)以及如何处理这些警告.恕我直言,那些其他答案_are_比我的好:). (5认同)
  • 当使用这样的for循环时,`key`将只占用一个索引值,因此只会提醒0,1,2等...你需要访问p [key]. (4认同)

Fra*_*wis 19

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

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

  • JSON对象是否干净是无关紧要的.如果在任何其他时间某些代码在`Object.prototype`上设置属性,那么它将由`for..in`枚举.如果您确定没有使用任何库,那么您不需要调用`hasOwnProperty`. (18认同)
  • 如果使用`Object.create(null)`创建它可以完全清理 (4认同)

bit*_*der 19

通过原型使用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
Run Code Online (Sandbox Code Playgroud)

  • 小心原型:`obj = {print:1,each:2,word:3}`产生`TypeError:number不是函数`.使用`forEach`匹配类似的`Array`函数可以稍微降低风险. (2认同)

Has*_*own 17

有趣的是,这些答案中的人都触及了两者Object.keys(),for...of但从未将它们结合起来:

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

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


您可以使普通对象关联迭代!Map直接使用for...of在Chrome和FF中工作的花哨
DEMO 就像s 一样(我假设只有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);
Run Code Online (Sandbox Code Playgroud)

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

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

无需创建一个没有良好语法糖的真实Map对象.

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

事实上,有了这个垫片,如果你仍然想利用Map的其他功能(没有全部填充它们),但仍然想使用整洁的对象表示法,因为对象现在是可迭代的,你现在可以从它制作一个Map!

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

对于那些不喜欢垫片,或者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;
}
Run Code Online (Sandbox Code Playgroud)

现在你可以把它称为普通函数,没有其他任何影响

var realMap = new Map(getObjIterator({well:'hello', there:'!'}))
Run Code Online (Sandbox Code Playgroud)

要么

for (let pair of getObjIterator(ordinaryObject))
Run Code Online (Sandbox Code Playgroud)

没有理由不这样做.

欢迎来到未来.

  • [案例](http://stackoverflow.com/a/19110204/2518317) [in](http://stackoverflow.com/a/19106881/2518317) [point](http://stackoverflow.com/a/ 21821236/2518317)。只要人们向下滚动并发现它有帮助,那就是最重要的。通常是我试图做某事,不喜欢我在网上看到的东西,最终弄清楚了,然后我回来分享。这是很好的 doco,在谷歌搜索我完全忘记的事情之前,我实际上已经找到了我自己的答案! (2认同)

Isa*_*ala 13

将您的对象传递给Object.keys(). 这将返回一个包含对象中所有键的数组。然后您可以使用 循环遍历数组map。使用obj[key]where objis 你的对象和keyis 地图迭代中的当前值,你可以获取该键/属性的值。

const obj = { name: "Jane", age: 50 };

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


Par*_*erz 12

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

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


Dmi*_*iko 12

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

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


Har*_*tel 12

这是迭代对象的另一种方法.

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


Object.keys(p).forEach(key => { console.log(key, p[key]) })
Run Code Online (Sandbox Code Playgroud)

  • 这很酷,但对于大型对象,`for`方法可能更高效. (3认同)

小智 11

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

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


One*_*era 9

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

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

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


小智 9

使用for-ofObject.keys()

喜欢:

let object = {
  "key1": "value1",
  "key2": "value2",
  "key3": "value3"
};

for (let key of Object.keys(object)) {
  console.log(key + " : " + object[key])
}
Run Code Online (Sandbox Code Playgroud)


Geo*_*ley 8

Object.keys()方法返回给定对象自己的可枚举属性的数组.在这里阅读更多相关信息

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

Object.keys(p).map((key)=> console.log(key + "->" + p[key]))
Run Code Online (Sandbox Code Playgroud)


akh*_*hid 8

在javascript中迭代对象的多种方法

使用for...in循环

 var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};
for (let key in p){
   if(p.hasOwnProperty(key)){
     console.log(`${key} : ${p[key]}`)
   }
}
Run Code Online (Sandbox Code Playgroud)

使用for...of循环

 var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};
for (let key of Object.keys(p)){
     console.log(`key: ${key} & value: ${p[key]}`)
}
Run Code Online (Sandbox Code Playgroud)

forEach()Object.keysObject.valuesObject.entries 一起使用

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};
Object.keys(p).forEach(key=>{
   console.log(`${key} : ${p[key]}`);
});
Object.values(p).forEach(value=>{
   console.log(value);
});
Object.entries(p).forEach(([key,value])=>{
    console.log(`${key}:${value}`)
})
Run Code Online (Sandbox Code Playgroud)


小智 8

Object.entries(myObject).map(([key, value]) => console.log(key, value))
Run Code Online (Sandbox Code Playgroud)

你可以这样尝试。myObject{name: "", phone: ""}如此这般,这会生成key和value。所以这里的关键是namephone价值就像dog, 123123

例子{name: "dog"}

这里的 key 是name, value 是dog


Bib*_*ber 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
});
Run Code Online (Sandbox Code Playgroud)

对于那些不喜欢" 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
});
Run Code Online (Sandbox Code Playgroud)

现在,您可以简单地致电:

p.forEach (function(key, value){
    console.log ("Key: " + key);
    console.log ("Value: " + value);
});
Run Code Online (Sandbox Code Playgroud)

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

  • 修改内置对象的原型(如`Object`)通常被认为是反模式,因为它很容易导致与其他代码冲突.所以伤口*不建议这样做. (3认同)

moh*_*him 6

只有没有依赖关系的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
}
Run Code Online (Sandbox Code Playgroud)


Ame*_*icA 6

在可枚举的 JavaScript 对象上循环的一个好方法是使用Object.keysObject.entries使用map函数。像下面这样:

// assume items:

const items = {
  first: { name: 'phone', price: 400 },
  second: { name: 'tv', price: 300 },
  third: { name: 'sofa', price: 250 },
};
Run Code Online (Sandbox Code Playgroud)

For 循环并显示一些 UIReactJS如下所示:

~~~
<div>
  {Object.entries(items).map(([key, ({ name, price })]) => (
    <div key={key}>
     <span>name: {name}</span>
     <span>price: {price}</span>
    </div>
  ))}
</div>
Run Code Online (Sandbox Code Playgroud)

实际上,我使用了两次解构赋值,一次用于获取key一次获取nameprice


Sah*_*mar 6

  1. 使用for...inObject hasOwnProperty

        var p = {
            "p1": "value1",
            "p2": "value2",
            "p3": "value3"
        };
    
        for (var key in p) {
            if (p.hasOwnProperty(key)) {
                console.log(key, ' : ', p[key]);
            }
        }
    Run Code Online (Sandbox Code Playgroud)

  2. 使用for...ofObject 键

        var p = {
          "p1": "value1",
          "p2": "value2",
          "p3": "value3"
        };
    
        for (var key of Object.keys(p)) {
          console.log(key, " : ", p[key])
        }
    Run Code Online (Sandbox Code Playgroud)

  3. 使用对象键forEach

        var p = {
            "p1": "value1",
            "p2": "value2",
            "p3": "value3"
        };
    
        Object.keys(p).forEach(function(key) {
            console.log(key, ' : ', p[key]);
        });
    Run Code Online (Sandbox Code Playgroud)

  4. 使用for...of对象条目

        var p = {
            "p1": "value1",
            "p2": "value2",
            "p3": "value3"
        };
    
        for (let [key, value] of Object.entries(p)) {
          console.log(key, ' : ', value);
        }
    Run Code Online (Sandbox Code Playgroud)

  5. 使用对象条目forEach

        var p = {
            "p1": "value1",
            "p2": "value2",
            "p3": "value3"
        };
    
        Object.entries(p).forEach(([key, value]) => console.log(key, ' : ', value));
    Run Code Online (Sandbox Code Playgroud)


Ran*_*ner 6

有几种选择:

  1. 你可以用for..in

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

for (const item in p) {
  console.log(`key = ${item}, value = ${p[item]}`);
}
Run Code Online (Sandbox Code Playgroud)

  1. 您还可以调用Object.entries()创建一个包含所有可枚举属性的数组。之后您可以使用map,foreach或循环遍历它for..of

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


Object.entries(p).map(item => {
  console.log(item)
})
Run Code Online (Sandbox Code Playgroud)

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


Object.entries(p).forEach(item => {
  console.log(item)
})
Run Code Online (Sandbox Code Playgroud)

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


for (const item of Object.entries(p)) {
  console.log(item)
}
Run Code Online (Sandbox Code Playgroud)

更多相关信息可以在这里Object.entries()找到


Lew*_*wis 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");
}
Run Code Online (Sandbox Code Playgroud)


Dhe*_*.S. 5

如果您还想迭代不可枚举的属性,则可以使用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/>');
});
Run Code Online (Sandbox Code Playgroud)

  • 这太棒了,感谢您发布这个答案。我需要内省一个 `Error` 对象,但无法获取循环或 `_.forIn(err)` 调用中的属性。使用“Object.getOwnPropertyNames(err)”允许我访问“Error”中我以前无法访问的所有部分。谢谢! (2认同)

Nic*_*tte 5

使用纯JavaScript时,循环可能非常有趣.似乎只有ECMA6(New 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;
  }
}
Run Code Online (Sandbox Code Playgroud)

此外,我知道这个问题超出了这个问题,但在2011年,ECMAScript 5.1 forEach仅为Arrays 添加了方法,它基本上创建了一种新的改进方法来循环遍历数组,同时仍然使用旧的详细和混乱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;
}
Run Code Online (Sandbox Code Playgroud)

请注意,截至2016年6月18日,大多数浏览器都不支持上述代码.即使在Chrome中,您也需要启用此特殊标记才能使其正常工作: chrome://flags/#enable-javascript-harmony

在这成为新标准之前,仍然可以使用旧方法,但是对于那些不使用任何这些库的人来说,流行的库中也有替代品,甚至是轻量级替代品.


Tad*_* V. 5

如果有人需要使用条件循环遍历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");
      }
   }
}
Run Code Online (Sandbox Code Playgroud)


Art*_*ich 5

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

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

for(let pValue of book){
  console.log(pValue);
}
------------------------
Amazing book
Me
3
Run Code Online (Sandbox Code Playgroud)

或者,如果您知道 ES6生成器的强大功能,那么您当然可以使上面的代码变得更短。

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

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

}
Run Code Online (Sandbox Code Playgroud)

当然,您可以将这种行为应用于所有对象,并使其Objectprototype级别上可迭代。

Object.prototype[Symbol.iterator] = function() {...}
Run Code Online (Sandbox Code Playgroud)

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

let pValues = [...book];
console.log(pValues);
-------------------------
["Amazing book", "Me", 3]
Run Code Online (Sandbox Code Playgroud)

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

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

您可以使用我上面提供的所有代码查看JSFiddle 。


Bam*_*ieh 5

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

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

[...p] //["p1", "p2", "p3"]
Run Code Online (Sandbox Code Playgroud)

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

for(var key in p) {
    console.log(key);
}
Run Code Online (Sandbox Code Playgroud)

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


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


yeh*_*kel 5

从 ES06 开始,您可以使用数组获取对象的值

let arrValues = Object.values( yourObject) ;
Run Code Online (Sandbox Code Playgroud)

它返回对象值的数组,而不是从 Prototype 中提取值!!

MDN DOCS Object.values()

和钥匙(在这里已经在我面前回答了)

let arrKeys   = Object.keys(yourObject);
Run Code Online (Sandbox Code Playgroud)


小智 5

最接近的解决方案,接近python的枚举函数:

for key, value in enumerate(object):
    # Do something
Run Code Online (Sandbox Code Playgroud)

Object.entries()是和循环的组合for-of

for(let [key, value] of Object.entries(object)) {
    // Do something
}
Run Code Online (Sandbox Code Playgroud)

for key, value in enumerate(object):
    # Do something
Run Code Online (Sandbox Code Playgroud)