我有一个如下的JavaScript对象:
var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};
现在我想通过所有回路p
元素(p1
,p2
,p3
...),并得到他们的键和值。我怎样才能做到这一点?
我可以根据需要修改JavaScript对象。我的最终目标是遍历一些键值对,如果可能,我想避免使用eval
。
我有一个如下的JavaScript对象:
var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};
现在我想通过所有回路p
元素(p1
,p2
,p3
...),并得到他们的键和值。我怎样才能做到这一点?
我可以根据需要修改JavaScript对象。我的最终目标是遍历一些键值对,如果可能,我想避免使用eval
。
Answers:
您可以使用for-in
其他人所示的循环。但是,您还必须确保获取的键是对象的实际属性,而不是来自原型。
这是代码段:
var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};
for (var key in p) {
if (p.hasOwnProperty(key)) {
console.log(key + " -> " + p[key]);
}
}
用Object.keys()替代:
var p = {
0: "value1",
"b": "value2",
key: "value3"
};
for (var key of Object.keys(p)) {
console.log(key + " -> " + p[key])
}
请注意,使用of for-of
代替for-in
,如果不使用它将在命名属性上返回未定义,并Object.keys()
确保仅使用对象自身的属性,而不使用整个原型链属性
使用新Object.entries()
方法:
注意: Internet Explorer本身不支持此方法。您可以考虑将Polyfill用于较旧的浏览器。
const p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};
for (let [key, value] of Object.entries(p)) {
console.log(`${key}: ${value}`);
}
alert(key + " -> " + JSON.stringify(p[key]));
__proto__
或的属性prototype
。此属性对其父对象有引用。对象自动从其父级继承属性。这是使用的原因hasOwnProperty
,它表示我们对对象拥有的属性(而不是其父属性)感兴趣。
在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
:
for (const [key, value] of Object.entries(obj)) {
console.log(key, value);
}
二者Object.keys()
并Object.entries()
以相同的顺序作为迭代性质for...in
环但忽略原型链。仅迭代对象自身的可枚举属性。
Object.forEach(obj, function (value, key) {...})
?:(当然obj.forEach(function...)
会更短和补充Array.prototype.forEach
,但将风险有对象定义自己的forEach
财产,我想,Object.keys
对回调警卫修改对象的关键。
Object.forEach = function (obj, callback) { Object.keys(obj).forEach(function (key) { callback(obj[key], key); }); }
Object.entries(obj).map/forEach(([key, value]) => console.log(key, value))
([键,值]是数组结构分解,可以直接访问两个项目。并且必须将参数包装在其他括号中。)
index
json中的密钥?或者,如果需要,我应该使用一个单独的计数器?
for...of
是ES6标准,而不是ES2016。
您必须使用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
}
{ }
个人删除,因为如果if
没有他们,会使您不清楚该部分的内容if
,哪些不是。但是我想这只是个意见问题:)
{ }
如果以后需要在if
示波器上添加一些内容,我倾向于保留主要内容以避免混淆。
Object.prototype.hasOwnProperty.call(p, prop)
但是,这也无法防止对Object.prototype的操纵...
如果我们不提及循环对象的替代方法,那么这个问题将是不完整的。
如今,许多知名的JavaScript库都提供了自己的方法来遍历集合,即遍历数组,对象和类似数组的对象。这些方法使用方便,并且与任何浏览器完全兼容。
如果使用jQuery,则可以使用jQuery.each()
method。它可以用来无缝地遍历对象和数组:
$.each(obj, function(key, value) {
console.log(key, value);
});
在Underscore.js中,您可以找到method _.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表
UPD:
此问题上所有最受欢迎案例的性能比较perfjs.info
:
前言:
在2018年,您可以使用以下选项遍历对象的属性(以下示例如下所示):
for-in
[ MDN,spec ] —循环结构,循环遍历对象的可枚举属性的名称,包括名称为字符串的继承属性Object.keys
[ MDN,规格 ] -提供一个对象的名称的数组的函数自己的,枚举的性质,其名称是字符串。Object.values
[ MDN,规格 ] -甲函数提供所述的阵列值的对象的的自己的,枚举的属性。Object.entries
[ MDN,规格 ] -提供所述名称的数组的函数和一个对象的值自身,可枚举属性(阵列中的每个条目是[name, value]
阵列)。Object.getOwnPropertyNames
[ MDN,spec ] —提供名称为字符串的对象自身属性(甚至是不可枚举的属性)名称数组的函数。Object.getOwnPropertySymbols
[ MDN,spec ] —一种函数,提供名称为Symbols 的对象自身属性(甚至是不可枚举的属性)名称的数组。Reflect.ownKeys
[ MDN,spec ] —一种函数,提供对象自身属性的名称(甚至是不可枚举的属性)名称的数组,无论这些名称是字符串还是符号。Object.getPrototypeOf
[ MDN,规格 ]和使用Object.getOwnPropertyNames
,Object.getOwnPropertySymbols
或Reflect.ownKeys
在原型链中的每个对象(例如,在此答案的底部)。随着所有这些硬盘中for-in
,你会使用某种类型的阵列上的循环结构(中for
,for-of
,forEach
,等)。
例子:
for-in
:
Object.keys
(带有for-of
循环,但是您可以使用任何循环构造):
Object.values
:
Object.entries
:
Object.getOwnPropertyNames
:
Object.getOwnPropertySymbols
:
Reflect.ownKeys
:
所有属性,包括继承的不可枚举的属性:
您可以像这样遍历它:
for (var key in p) {
alert(p[key]);
}
请注意,它key
不会采用属性的值,而只是一个索引值。
由于es2015越来越受欢迎,因此我发布了此答案,其中包括使用generator和iterator来平滑地遍历[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
和其他属性上进行迭代。
key
将仅采用一个索引值,这样将仅警告0、1、2等。您需要访问p [key]。
var p = {"p1":"q","p2":"w"}; for(key in p) { alert( key ); }
在警报中弹出“ p1”和“ p2”,那怎么了???
在查看完所有答案之后,我自己的用法不需要hasOwnProperty,因为我的json对象是干净的;添加任何额外的javascript处理确实没有任何意义。这就是我正在使用的:
for (var key in p) {
console.log(key + ' => ' + p[key]);
// key is key
// value is p[key]
}
Object.prototype
,则该属性将由枚举for..in
。如果确定没有使用任何执行此操作的库,则无需调用hasOwnProperty
。
Object.create(null)
通过原型与的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
obj = { print: 1, each: 2, word: 3 }
产生TypeError: number is not a function
。使用forEach
相匹配的类似Array
功能可能会有所降低风险。
有趣的是,这些答案中的人都涉及到了两个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
s 一样,直接使用for...of
在Chrome和FF中运行的精美
DEMO(我假设仅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))
欢迎来到未来。
For those who don't like to shim, or mess with prototype in general, feel free to make the function on window instead, calling it something like getObjIterator() then;
ordinaryObject
强调魔术仍然适用于这些类型的变量)。你检查演示了吗?什么对你不起作用,@noɥʇʎԀʎzɐɹƆ?(请注意,您的SE个人资料图片是老板)
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中,我得到以下结果
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);
});
这是另一种遍历对象的方法。
var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};
Object.keys(p).forEach(key => { console.log(key, p[key]) })
for
方法可能会更有效。
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>
您还可以使用Object.keys()并遍历如下所示的对象键来获取值:
var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};
Object.keys(p).forEach((key)=> {
console.log(key +' -> '+ p[key]);
});
今天,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)解决方案可以在铬上快速处理大小物体i
(J,K)的解决方案在所有浏览器中对小对象的响应都非常快(对于Firefox,对于大型对象也是如此,而在其他浏览器中则为中等)为执行性能测试
以下摘录介绍了二手解决方案
这是镀铬小物件的结果
您可以向所有对象添加一个简单的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
});
对于那些不喜欢“ -... ”方法的人:
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发生冲突,可以使用唯一的名称来命名。
Object
)的原型通常被认为是一种反模式,因为它很容易引起与其他代码的冲突。所以伤口不建议这样做。
使用纯JavaScript时,循环可能非常有趣。似乎只有ECMA6(新的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
仅添加了用于数组的方法,该方法基本上创建了一种新的改进方法来遍历数组,同时仍然使旧的冗长而混乱的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
在成为新标准之前,仍然可以使用旧方法,但是流行的库中还有其他选择,甚至对于那些不使用这些库的人来说,甚至还有轻量级的选择。
Uncaught TypeError: Object.entries is not a function
。尚未在Chrome中实现吗?
在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现在所具有的功能很重要!
Object.keys()
内存生成并在内存中分配的数组的内置数组迭代器。
我会这样做,而不是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");
}
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]);
}
}
}
json = [{"key1":"value1","key2":"value2"},{"key1":"value3","key2":"value4"}] for (var i = 0; i < json.length; i++) { for (var key in json[i]) { if (json[i].hasOwnProperty(key)) { console.log(key + " -> " + json[i][key]); } } }
使用for-of
开Object.keys()
喜欢:
let object = {
"key1": "value1"
"key2": "value2"
"key3": "value3"
};
for (var key of Object.keys(p)) {
console.log(key + " : " + object[key])
}
如果您还想遍历不可枚举的属性,则可以使用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/>');
});
Error
对象,并且无法在循环或_.forIn(err)
调用中获得属性。使用Object.getOwnPropertyNames(err)
使我可以访问Error
以前无法获得的所有部分。谢谢!
如果有人需要遍历带有条件的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");
}
}
}
考虑到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 };
}
既然我们做到了,我们就可以这样使用它:
for(let pValue of book){
console.log(pValue);
}
------------------------
Amazing book
Me
3
或者,如果您知道ES6 生成器的功能,那么您当然可以使上面的代码更短。
book[Symbol.iterator] = function *(){
let properties = Object.keys(this);
for (let p of properties){
yield this[p];
}
}
当然,您可以Object
在prototype
级别可迭代的情况下将此类行为应用于所有对象。
Object.prototype[Symbol.iterator] = function() {...}
而且,符合迭代协议的对象可与新的ES2015功能扩展运算符一起使用,因此我们可以将对象属性值读取为数组。
let pValues = [...book];
console.log(pValues);
-------------------------
["Amazing book", "Me", 3]
或者您可以使用解构分配:
let [title, , pages] = book; // notice that we can just skip unnecessary values
console.log(title);
console.log(pages);
------------------
Amazing book
3
您可以使用上面提供的所有代码签出JSFiddle。
从ES06开始,您可以使用
let arrValues = Object.values( yourObject) ;
它返回对象值的数组,并且不从原型中提取值!
和钥匙(在这里我已经回答了)
let arrKeys = Object.keys(yourObject);