我有一个像以下JavaScript对象:
var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};
现在我想循环遍历所有p
元素(p1
,p2
,p3
......)并获得他们的键和值。我怎样才能做到这一点?
如有必要,我可以修改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]);
}
}
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和其他属性。
通过原型使用forEach(),它应该跳过原型链属性:
for (var key in p) {
console.log(key + ' => ' + p[key]);
// key is key
// value is p[key]
}
有趣的是,这些答案的人都触及了for(key in p) {
alert( p[key] );
}
和length
,但从未合并过:
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.keys()
和for...of
,因为它不是一个迭代器,而var map = {well:'hello', there:'!'};
for (let key of Object.keys(map))
console.log(key + ':' + map[key]);
或for...of
ing Object
是丑陋/低效的。
我很高兴大多数人都避免使用for...index
(有或没有检查.forEach()
),因为这也有点凌乱,所以除了上面的回答,我在这里说...
您可以使普通对象关联迭代!像Object.keys()
s一样直接使用花式for...in
.hasOwnProperty()
在Chrome和FF工作(我假设只有ES6)
Map
只要你在下面包括我的垫片:
for...of
无需创建一个没有良好语法糖的真实Map对象。
DEMO
事实上,有了这个垫片,如果你仍然想利用Map的其他功能(没有全部填充它们),但仍想使用整洁的对象表示法,因为对象现在是可迭代的,你现在可以从它制作一个Map!
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;
}};
};
混淆的人,可以随意在窗口上制作功能,然后将其称为var trueMap = new Map([['well', 'hello'], ['there', '!']]);
for (let pair of trueMap)
console.log(pair[0] + ':' + pair[1]);
;
//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;
}
欢迎来到未来。
Object.keys(obj):数组
检索所有可枚举的自有(非继承)属性的所有字符串值。
因此,它通过使用hasOwnProperty测试每个对象键来提供与您想要的相同的键列表。你不需要额外的测试操作,而且var realMap = new Map(getObjIterator({well:'hello', there:'!'}))
应该更快。让我们证明一下:
for (let pair of getObjIterator(ordinaryObject))
在我的Firefox中,我有以下结果
PS。在Chrome上差异甚至更大的There's no reason why that wouldn't work.
PS2:在ES6(EcmaScript 2015)中,您可以更好地迭代可迭代对象:
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.");
http://codepen.io/dsheiko/pen/JdrqXa
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);
});
var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};
Object.keys(p).forEach(key => { console.log(key, p[key]) })
方法返回给定对象自己的可枚举属性的数组。阅读更多关于它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>
您可以向所有对象添加一个简单的forEach函数,因此您可以自动遍历任何对象:
Object.keys()
对于那些不喜欢“for ... in”的人 - 方法:
here
现在,您可以简单地致电:
var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};
Object.keys(p).map((key)=> console.log(key + "->" + p[key]))
如果您不想与其他forEach-Methods发生冲突,可以使用您的唯一名称命名。
只有没有依赖关系的JavaScript代码:
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
});
使用纯JavaScript时,循环可能非常有趣。似乎只有ECMA6(New 2015 JavaScript规范)才能控制循环。不幸的是,当我写这篇文章时,浏览器和流行的集成开发环境(IDE)仍然在努力完全支持新的花里胡哨。
这一点是ECMA6之前的JavaScript对象循环:
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
});
此外,我知道这个问题超出了这个问题,但在2011年,ECMAScript 5.1仅为Arrays添加了p.forEach (function(key, value){
console.log ("Key: " + key);
console.log ("Value: " + value);
});
方法,它基本上创建了一种新的改进方法来循环遍历数组,同时仍然使用旧的冗长和令人困惑的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
}
循环留下不可迭代的对象。但奇怪的是,这种新的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;
}
}
方法不支持导致各种其他问题的forEach
。
基本上在2011年,除了许多流行的库(jQuery,Underscore等)决定重新实现之外,没有一种真正可靠的JavaScript循环方式。
截至2015年,我们现在有一个更好的开箱即用方式来循环(和中断)任何对象类型(包括数组和字符串)。以下是当推荐成为主流时,JavaScript中的循环最终会是什么样子:
for
请注意,截至2016年6月18日,大多数浏览器都不支持上述代码。即使在Chrome中,您也需要启用此特殊标记才能生效:forEach
在这成为新标准之前,仍然可以使用旧方法,但是对于那些没有使用任何这些库的人来说,在流行的库中甚至还有break
也有替代方法。
在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
,destructuring和Object.entries
:
for (const [key, value] of Object.entries(obj)) {
console.log(key, value);
}
Object.keys()
和Object.entries()
都以与for...in
循环相同的顺序迭代属性,但忽略原型链。只迭代对象自己的可枚举属性。
for (let [key, value] of Object.entries(object)) {
console.log(key); // This is the key;
console.log(value); // This is the value;
}
考虑到ES6,我想添加自己的糖,并提供一种迭代对象属性的方法。
由于普通的JS对象不是开箱即用的chrome://flags/#enable-javascript-harmony
,我们无法使用lightweight alternatives循环来迭代其内容。但没有人可以阻止我们使其可迭代。
让我们有 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]);
}
}
}
对象。
iterable
既然我们已经成功了,我们就可以这样使用它:
for..of
或者如果你知道ES6 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
级别上使generators可迭代地对所有对象应用此类行为。
book[Symbol.iterator] = function *(){
let properties = Object.keys(this);
for (let p of properties){
yield this[p];
}
}
此外,符合可迭代协议的对象可以与新的ES2015特性Object
运算符一起使用,因此我们可以将对象属性值作为数组读取。
prototype
或者你可以使用Object.prototype[Symbol.iterator] = function() {...}
赋值:
spread
你可以查看我上面提供的所有代码的let pValues = [...book];
console.log(pValues);
-------------------------
["Amazing book", "Me", 3]
。
在ES6中,我们使用众所周知的符号来公开一些以前的内部方法,您可以使用它来定义迭代器如何为此对象工作:
destructuring
这将给出与在es6循环中使用for ...相同的结果。
let [title, , pages] = book; // notice that we can just skip unnecessary values
console.log(title);
console.log(pages);
------------------
Amazing book
3
但了解现在使用es6的功能非常重要!
我会这样做而不是在每个JSFiddle循环中检查var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3",
*[Symbol.iterator]() {
yield *Object.keys(this);
}
};
[...p] //["p1", "p2", "p3"]
。
for(var key in p) {
console.log(key);
}
从ES06开始,您可以将对象的值作为数组获取
obj.hasOwnerProperty
它返回一个对象值的数组,它不从Prototype中提取值!
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");
}
如果你想迭代let arrValues = Object.values( yourObject) ;
,你可以使用MDN DOCS Object.values()返回一个直接在给定对象上找到的所有属性(可枚举或不可枚举)的数组。
let arrKeys = Object.keys(yourObject);
如果有人需要循环遍历具有条件的数组对象:
在最新的ES脚本中,您可以执行以下操作:
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/>');
});
功能:
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");
}
}
}
使用Angular时遇到了类似的问题,这是我找到的解决方案。
步骤1.获取所有对象键。使用Object.keys。此方法返回给定对象自己的可枚举属性的数组。
步骤2.创建一个空数组。这是所有属性都将存在的地方,因为你的新ngFor循环将指向这个数组,我们必须全部捕获它们。步骤3.迭代抛出所有键,并将每个键推入您创建的数组中。这是代码中的样子。
Object.entries(p);
这是原始帖子的链接。 Object.entries()
你必须使用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
}
实现.next()方法时,对象成为迭代器
var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};
for (var i in Object.entries(p)){
var key = Object.entries(p)[i][0];
var value = Object.entries(p)[i][1];
console.log('key['+i+']='+key+' '+'value['+i+']='+value);
}
如果我们不提及循环对象的替代方法,那么问题就不会完整。
如今,许多众所周知的JavaScript库提供了自己的迭代集合的方法,即在数组,对象和类似数组的对象上。这些方法使用方便,并且与任何浏览器完全兼容。
jQuery.each()
方法。它可用于无缝迭代对象和数组:
$.each(obj, function(key, value) {
console.log(key, value);
});
_.each()
,它迭代一个元素列表,然后依次产生一个提供的函数(注意iteratee函数中参数的顺序!):
_.each(obj, function(value, key) {
console.log(key, value);
});
_.forEach()
(或它的别名_.each()
)对于循环遍历对象和数组非常有用,但是(!)具有length
属性的对象被视为数组,并且为了避免这种行为,建议使用_.forIn()
和_.forOwn()
方法(这些方法也有value
)争论第一):
_.forIn(obj, function(value, key) {
console.log(key, value);
});
_.forIn()
迭代对象的自有和继承的可枚举属性,而_.forOwn()
仅迭代对象的自有属性(基本上检查hasOwnProperty
函数)。对于简单对象和对象文字,这些方法中的任何一种都可以正常工作。通常,所有描述的方法与任何提供的对象具有相同的行为。除了使用本机for..in
循环通常会比任何抽象更快,例如jQuery.each()
,这些方法相当容易使用,需要更少的编码并提供更好的错误处理。
在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's compat table上看到的浏览器支持
UPD:
在perfjs.info
上这个问题中所有最受欢迎的案例的性能比较:
您可以像以下一样迭代它:
for (var key in p) {
alert(p[key]);
}
请注意,key
不会采用属性的值,它只是一个索引值。
前言:
在2018年,您在循环对象属性的选项是(一些示例遵循列表):
for-in
[MDN,spec] - 循环结构,循环遍历对象的可枚举属性的名称,包括继承的属性,其名称为字符串Object.keys
[MDN,spec] - 一个函数,提供一个对象自己的名称数组,其名称为字符串。Object.values
[MDN,spec] - 一个函数,提供对象自身可枚举属性的值数组。Object.entries
数组)。[name, value]
] - 一个函数,提供一个对象自己的属性名称数组(甚至是不可枚举的属性),其名称为字符串。Object.getOwnPropertyNames
[MDN,spec] - 一个函数,提供一个对象自己的属性名称数组(甚至是不可枚举的属性),其名称为Symbols。Object.getOwnPropertySymbols
[MDN,spec] - 一个函数,提供对象自身属性的名称数组(甚至是不可枚举的属性),无论这些名称是字符串还是符号。Reflect.ownKeys
[MDN,spec]并在原型链中的每个对象上使用Object.getPrototypeOf
,MDN或spec(示例位于底部这个答案)。除了Object.getOwnPropertyNames
之外的所有这些,你都会在数组上使用某种循环结构(Object.getOwnPropertySymbols
,Reflect.ownKeys
,for-in
等)。
例子:
for
:
for-of
forEach
(使用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
由于es2015越来越受欢迎,我发布这个答案,包括使用生成器和迭代器来顺利迭代// 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}`);
}
对。因为在其他语言中可以使用例如Ruby。
好的,这是一个代码:
// 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)}`);
}
}
有关如何在开发人员Mozilla页面上找到迭代器和生成器的所有信息。
希望它帮助了某个人。
编辑:
ES2017将包括.as-console-wrapper {
max-height: 100% !important;
}
,它将使对象中的[key, value]
对迭代更加容易。现在已知根据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}`);
}
阶段信息它将成为标准的一部分。
我认为现在是时候更新我的答案,让它变得比现在更新鲜。
Object.entries
您可以在[key, value]
页面上找到有关使用的更多信息
在查看了这里的所有答案之后,我自己的用法不需要hasOwnProperty,因为我的json对象是干净的;添加任何额外的JavaScript处理真的没有意义。这就是我正在使用的:
ts39