我有一个像以下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]);
}
}
在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
迭代特性以相同的次序作为Object.keys()
环但忽略原型链.只迭代对象自己的可枚举属性.
你必须使用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库提供了自己的迭代集合的方法,即在数组,对象和类似数组的对象上.这些方法使用方便,并且与任何浏览器完全兼容.
如果您使用jQuery,您可以使用jQuery.each()
方法.它可用于无缝迭代对象和数组:
$.each(obj, function(key, value) { console.log(key, value); });
在Underscore.js中,你可以找到方法_.each()
,它迭代一个元素列表,然后依次产生一个提供的函数(注意iteratee函数中参数的顺序!):
_.each(obj, function(value, key) { console.log(key, value); });
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()
,这些方法使用起来更简单,需要更少的编码并提供更好的错误处理.
在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
:
对象文字迭代
您可以像以下一样迭代它:
for (var key in p) { alert(p[key]); }
请注意,key
不会采用属性的值,它只是一个索引值.
前言:
对象属性可以是自己的(属性在对象本身上)或继承(不在对象本身上,在其中一个原型上).
对象属性可以是可枚举的或不可枚举的.不可枚举的属性被排除在许多属性枚举/数组之外.
属性名称可以是字符串或符号.名称为Symbols的属性不包含许多属性枚举/数组.
在2018年,您循环访问对象属性的选项是:
for-in
[ MDN,spec ] - 循环结构,循环访问对象的可枚举属性的名称,包括继承的属性,其名称为字符串
Object.keys
[ MDN,规格 ] -提供一个对象的名称的数组的函数自己的,枚举的性质,其名称是字符串.
Object.values
[ MDN,规格 ] -提供所述的阵列函数值对象的的自己的,枚举的属性.
Object.entries
[ MDN,规格 ] -提供所述名称的数组的函数和一个对象的值自身,可枚举的属性.
[name, value]
[ MDN,spec ] - 一个函数,提供一个对象自己的属性名称数组(甚至是不可枚举的属性),其名称为字符串.
Object.getOwnPropertyNames
[ MDN,spec ] - 一个函数,提供一个对象自己的属性名称数组(甚至是不可枚举的属性),其名称为Symbols.
Object.getOwnPropertySymbols
[ MDN,spec ] - 一个函数,提供对象自身属性的名称数组(甚至是不可枚举的属性),无论这些名称是字符串还是符号.
如果你想所有对象的属性,包括不可枚举的继承者,你需要使用一个循环,Reflect.ownKeys
[ MDN,规格 ]和使用Object.getPrototypeOf
,Object.getOwnPropertyNames
或Object.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}`);
}
由于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(key in p) { alert( p[key] ); }
注意:您可以在数组上执行此操作,但您也将遍历length
其他属性.
在查看了这里的所有答案之后,我自己的用法不需要hasOwnProperty,因为我的json对象是干净的; 添加任何额外的JavaScript处理真的没有意义.这就是我正在使用的:
for (var key in p) { console.log(key + ' => ' + p[key]); // key is key // value is p[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.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
在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);
只要你在下面包括我的垫片:
//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]);
}
}
Output:
p1 = values1
p2 = values2
p3 = values3
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.");
这是迭代对象的另一种方法.
var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};
Object.keys(p).forEach(key => { console.log(key, p[key]) })
您还可以使用Object.keys()并遍历如下所示的对象键来获取值:
var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};
Object.keys(p).forEach((key)=> {
console.log(key +' -> '+ p[key]);
});
该Object.keys()
方法返回给定对象自己的可枚举属性的数组.在这里阅读更多相关信息
var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};
Object.keys(p).map((key)=> console.log(key + "->" + p[key]))
您可以向所有对象添加一个简单的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发生冲突,可以使用您的唯一名称命名.
只有没有依赖关系的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(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; } }
此外,我知道这个问题超出了这个问题,但在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; }
请注意,截至2016年6月18日,大多数浏览器都不支持上述代码.即使在Chrome中,您也需要启用此特殊标记才能使其正常工作: chrome://flags/#enable-javascript-harmony
在这成为新标准之前,仍然可以使用旧方法,但是对于那些不使用任何这些库的人来说,流行的库中也有替代品,甚至是轻量级替代品.
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]);
}
}
}