我有一个如下的JavaScript对象:
var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};
现在,我想遍历所有p
元素( p1
, p2
, p3
...),并获取它们的键和值。 我怎样才能做到这一点?
我可以根据需要修改JavaScript对象。 我的最终目标是遍历一些键值对,如果可能的话,我想避免使用eval
。
#1楼
通过原型用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楼
如果我们不提及循环对象的替代方法,那么这个问题将是不完整的。
如今,许多知名的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提供了几种遍历对象属性的方法。 基本的
_.forEach()
(或别名_.each()
)对于循环遍历对象和数组很有用,但是具有length
属性的(!)对象被视为数组,并且为避免这种现象,建议使用_.forIn()
和_.forOwn()
方法(这些方法也首先使用value
参数):_.forIn(obj, function(value, key) { console.log(key, value); });
_.forIn()
遍历对象的自身和继承的可枚举属性,而_.forOwn()
仅遍历对象的自身属性(基本上检查hasOwnProperty
函数)。 对于简单的对象和对象文字,这些方法中的任何一种都可以正常工作。
通常,所有描述的方法对于任何提供的对象都具有相同的行为。 除了使用native for..in
循环通常比任何抽象方法jQuery.each()
例如jQuery.each()
都快 ,这些方法更易于使用,需要更少的编码并提供更好的错误处理。
#3楼
在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表上看到的浏览器支持
UPD:
perfjs.info
上此问题中所有最流行情况的性能比较:
#4楼
仅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
}
#5楼
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); });
#6楼
我会这样做,而不是在每个for ... in
循环中检查obj.hasOwnerProperty
。
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");
}
#7楼
如果还想遍历不可枚举的属性