loops js遍历对象 - 如何循环或枚举JavaScript对象?




js获取对象的key js对象数组 (25)

从ES06开始,您可以将对象的值作为数组获取

let arrValues = Object.values( yourObject) ;

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

MDN DOCS Object.values()

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

let arrKeys   = Object.keys(yourObject);

我有一个像以下JavaScript对象:

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

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

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


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

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

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

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

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

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

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

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


使用纯JavaScript时,循环可能非常有趣。 似乎只有ECMA6(New 2015 JavaScript规范)才能控制循环。 不幸的是,当我写这篇文章时,浏览器和流行的集成开发环境(IDE)仍在努力完全支持新的花里胡哨。

这里是一个JavaScript对象循环在ECMA6之前的样子:

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仅为Arrays添加了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

在此之前成为新的标准,仍然可以使用老方法,但也有在流行的库的替代品,甚至轻量级替代谁是不使用任何这些库的那些。


您可以向所有对象添加一个简单的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 ”-method的人:

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


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

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


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


前言:

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

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

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

对于除了for-in之外的所有这些,你将在数组上使用某种循环结构( forfor-offorEach等)。

例子:

for-in

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

Object.keys (带有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 name of Object.keys(o)) {
    const value = o[name];
    console.log(`${name} = ${value}`);
}

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 value of Object.values(o)) {
    console.log(`${value}`);
}

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, value] of Object.entries(o)) {
    console.log(`${name} = ${value}`);
}

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.getOwnPropertyNames(o)) {
    const value = o[name];
    console.log(`${name} = ${value}`);
}

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 Object.getOwnPropertySymbols(o)) {
    const value = o[name];
    console.log(`${String(name)} = ${value}`);
}

Reflect.ownKeys

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

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

// 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)}`);
    }
}
.as-console-wrapper {
  max-height: 100% !important;
}


由于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页面上找到有关使用的更多信息


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

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

如果您想迭代非可枚举属性,则可以使用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/>');
});


在ECMAScript 5中,您在文字的迭代字段中有了新方法 - Object.keys

您可以在Object.keys()看到更多信息

我的选择如下是当前版本浏览器中的更快解决方案(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表上看到浏览器支持

对于旧浏览器,您有simpleObject.keys() polyfill

UPD:

perfjs.info上这个问题中所有最受欢迎的案例的性能比较:

对象文字迭代


在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)
);

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


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

这是片段:

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

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


在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的功能非常重要!


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

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

Object.entries(p);

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

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

如果你只想对属性进行迭代,请使用上面的一个答案,但是如果你想迭代包括函数在内的所有东西,那么你可能想要使用Object.getOwnPropertyNames(obj)

for (let o of Object.getOwnPropertyNames(Math)) {
  console.log(o);
}

我有时使用它来快速测试具有简单输入和输出的对象上的所有函数。


使用Angular时遇到了类似的问题,这是我找到的解决方案。

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

步骤2.创建一个空数组。这是所有属性都将存在的地方,因为你的新ngFor循环将指向这个数组,我们必须全部捕获它们。步骤3.迭代抛出所有键,并将每个键推入您创建的阵列中。这是代码中的样子。

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

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


有趣的是,这些答案中的人都触及了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() )因为这也有点乱,所以除了上面的回答,我在这里说...

你可以让普通的对象关联迭代! 就像Map一样,直接使用for...of幻想
DEMO在Chrome和FF中工作(我假设只有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))

没有理由说这不起作用。

欢迎来到未来。


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>


    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]);
        }
    }
}


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


实现.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

如果要循环遍历数组,请使用标准的三部分for循环。

for (var i = 0; i < myArray.length; i++) {
    var arrayItem = myArray[i];
}

您可以通过缓存myArray.length或向后迭代来获得一些性能优化。





javascript loops each