问:
我有一个 JavaScript 对象,如下所示:
var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};
如何循环遍历 p 的所有元素(p1、p2、p3…)并获取它们的键和值?
答1:
与HuntsBot一起,探索全球自由职业机会–huntsbot.com
您可以使用其他人所示的 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§) { console.log(key + " -> " + p[key]) }
注意使用 for-of 而不是 for-in,如果不使用它将在命名属性上返回 undefined,并且 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}`);
}
在 javascript 中,每个对象都有一堆具有元信息的内置键值对。当您遍历对象的所有键值对时,您也在遍历它们。 hasOwnPropery() 过滤掉这些。
实际上,For...in 并未被弃用。 For each...in 是。但我真的很喜欢archaeologists这个词……我将不得不开始使用它。
如何添加循环的值?谢谢
(for..in) 用于对象,(for.. of) 用于数组
感谢您的简单回答。它节省了我的时间。
答2:
打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!
在 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 可以防止回调修改对象的键。
答3:
与HuntsBot一起,探索全球自由职业机会–huntsbot.com
您必须使用 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
}
这比 levik 的解决方案要好,因为它允许主逻辑只有一个嵌套循环,而不是两个;使代码更易于阅读。虽然我会松开 continue 周围的括号;它们是多余的。
我不会亲自删除 { },因为没有它们的 if 会让人有点不清楚什么是 if 的一部分,什么不是。但我想这只是一个意见问题:)
是的,我更喜欢保留 { },主要是为了避免以后需要在 if 范围内添加某些内容时造成混淆。
阅读我之前的评论,我意识到我没有使用正确的术语,因为我说的是“如果范围”;但请记住,JavaScript 仅具有函数作用域。所以我真正的意思是“如果阻止”。
“不幸的是,hasOwnProperty 是一种方法,而不是运算符,因此在任何对象中,它都可以替换为不同的函数,甚至是不是函数的值”
答4:
huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。
如果我们不提到循环对象的替代方法,这个问题就不会完整。
如今,许多著名的 JavaScript 库都提供了自己的方法来迭代集合,即遍历数组、对象和类数组对象。这些方法使用方便,完全兼容任何浏览器。
如果你使用 jQuery,你可以使用 jQuery.each() 方法。它可用于无缝迭代对象和数组: $.each(obj, function(key, value) { console.log(key, value); });在 Underscore.js 中,您可以找到方法 .each(),它遍历元素列表,将每个元素依次生成给提供的函数(注意 iteratee 函数中参数的顺序!):.each(obj,函数(值,键){ console.log(键,值);}); Lo-Dash 提供了几种迭代对象属性的方法。基本的 _.forEach()(或者它的别名 _.each())对于循环遍历对象和数组很有用,但是(!)具有长度属性的对象被视为数组,为了避免这种行为,建议使用 _ .forIn() 和 _.forOwn() 方法(这些也有值参数首先出现): _.forIn(obj, function(value, key) { console.log(key, value); }); _.forIn() 迭代对象自己的和继承的可枚举属性,而 _.forOwn() 仅迭代对象自己的属性(基本上检查 hasOwnProperty 函数)。对于简单的对象和对象字面量,这些方法中的任何一个都可以正常工作。
通常,所有描述的方法与任何提供的对象具有相同的行为。除了使用原生 for…in 循环通常比任何抽象(例如 jQuery.each())更快,这些方法更容易使用,需要更少的编码并提供更好的错误处理。
保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com
获取值: $.each(obj, function (key, value) { console.log(value.title); });
有趣的是下划线和jquery如何更改参数:)
答5:
一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会
前言:
对象属性可以是自己的(属性在对象本身上)或继承(不在对象本身上,在其原型之一上)。
对象属性可以是可枚举的或不可枚举的。不可枚举的属性被排除在许多属性枚举/数组之外。
属性名称可以是字符串或符号。名称为符号的属性被排除在许多属性枚举/数组之外。
在 2018 年,您可以选择循环遍历对象的属性(列表后面有一些示例):
for-in [MDN, spec] — 一种循环结构,循环遍历对象的可枚举属性的名称,包括继承的属性,其名称为字符串 Object.keys [MDN, spec] — 提供对象名称数组的函数对象自己的、名称为字符串的可枚举属性。 Object.values [MDN, spec] — 一个函数,提供对象自身的可枚举属性的值数组。 Object.entries [MDN, spec] — 一个函数,提供对象自身的可枚举属性的名称和值的数组(数组中的每个条目都是一个 [name, value] 数组)。 Object.getOwnPropertyNames [MDN, spec] — 一个函数,提供名称为字符串的对象自身属性(甚至是不可枚举属性)的名称数组。 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:
// 要继承的原型对象,具有字符串命名的属性 const p = {answer: 42}; // 我们要查看的对象,它继承自 p
const o = Object.create§; // 一个字符串命名的属性 o.question = “Life, the Universe, and Everything”; // 以交易品种命名的属性 o[Symbol(“author”)] = “Douglas Adams”; for (const name in o) { const value = o[name]; console.log(${name} = ${value}
); }
Object.keys (带有 for-of 循环,但您可以使用任何循环结构):
// 要继承的原型对象,具有字符串命名的属性 const p = {answer: 42}; // 我们要查看的对象,它继承自 p
const o = Object.create§; // 一个字符串命名的属性 o.question = “Life, the Universe, and Everything”; // 以交易品种命名的属性 o[Symbol(“author”)] = “Douglas Adams”; for (const name of Object.keys(o)) { const value = o[name]; console.log(${name} = ${value}
); }
Object.values:
// 要继承的原型对象,具有字符串命名的属性 const p = {answer: 42}; // 我们要查看的对象,它继承自 p
const o = Object.create§; // 一个字符串命名的属性 o.question = “Life, the Universe, and Everything”; // 以交易品种命名的属性 o[Symbol(“author”)] = “Douglas Adams”; for (Object.values(o) 的常量值) { console.log(${value}
); }
Object.entries:
// 要继承的原型对象,具有字符串命名的属性 const p = {answer: 42}; // 我们要查看的对象,它继承自 p
const o = Object.create§; // 一个字符串命名的属性 o.question = “Life, the Universe, and Everything”; // 以交易品种命名的属性 o[Symbol(“author”)] = “Douglas Adams”; for (const [name, value] of Object.entries(o)) { console.log(${name} = ${value}
); }
Object.getOwnPropertyNames:
// 要继承的原型对象,具有字符串命名的属性 const p = {answer: 42}; // 我们要查看的对象,它继承自 p
const o = Object.create§; // 一个字符串命名的属性 o.question = “Life, the Universe, and Everything”; // 以交易品种命名的属性 o[Symbol(“author”)] = “Douglas Adams”; for (Object.getOwnPropertyNames(o) 的常量名称) { 常量值 = o[name]; console.log(${name} = ${value}
); }
Object.getOwnPropertySymbols:
// 要继承的原型对象,具有字符串命名的属性 const p = {answer: 42}; // 我们要查看的对象,它继承自 p
const o = Object.create§; // 一个字符串命名的属性 o.question = “Life, the Universe, and Everything”; // 以交易品种命名的属性 o[Symbol(“author”)] = “Douglas Adams”; for (Object.getOwnPropertySymbols(o) 的常量名称) { 常量值 = o[名称]; console.log(${String(name)} = ${value}
); }
Reflect.ownKeys:
// 要继承的原型对象,具有字符串命名的属性 const p = {answer: 42}; // 我们要查看的对象,它继承自 p
const o = Object.create§; // 一个字符串命名的属性 o.question = “Life, the Universe, and Everything”; // 以交易品种命名的属性 o[Symbol(“author”)] = “Douglas Adams”; for (Reflect.ownKeys(o) 的常量名称) { 常量值 = o[name]; console.log(${String(name)} = ${value}
); }
所有属性,包括继承的不可枚举属性:
// 要继承的原型对象,具有字符串命名的属性 const p = {answer: 42}; // 我们要查看的对象,它继承自 p
const o = Object.create§; // 一个字符串命名的属性 o.question = “Life, the Universe, and Everything”; // 以交易品种命名的属性 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; }
很好地添加了可枚举/不可枚举的对象属性。
答6:
打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!
你可以像这样迭代它:
for (var key in p) {
alert(p[key]);
}
请注意,key 不会采用属性的值,它只是一个索引值。
这是重复的,甚至不完全正确。您需要检查 hasOwnProperty 以使其正常工作
我最初根据上述评论对此表示反对,直到我意识到这个答案是第一位的,因此不是“重复的”。它可能不完整,但在许多情况下都可以正常工作。
答7:
huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!
在 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 上看到浏览器支持
对于旧浏览器,您有 simple 和 full polyfill
升级版:
perfjs.info 上此问题中所有最流行案例的性能比较:
object literal iteration
确实,我只是想发布此方法。但是你打败了我:(
答8:
一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会
表现
今天 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) 解决方案在 chrome 上对于大小物体来说速度很快
基于显式索引 i (J,K) 的解决方案在小对象的所有浏览器上都非常快(对于大对象来说,Firefox 也很快,但在其他浏览器上速度中等)
基于迭代器 (D,E) 的解决方案最慢,不推荐
解决方案 C 对于大物体来说是慢的,对于小物体来说是中慢的
https://i.stack.imgur.com/M6NzO.png
细节
进行了性能测试
小对象 - 有 3 个字段 - 您可以在您的机器上执行测试这里
‘大’ 对象 - 有 1000 个字段 - 你可以在你的机器上执行测试 这里
下面的片段介绍了使用的解决方案
function A(obj,s=‘’) { for (let key in obj) if (obj.hasOwnProperty(key)) s+=key+‘->’+obj[key] + ’ ‘;返回 s; } function B(obj,s=’‘) { for (let key in obj) s+=key+’->‘+obj[key] + ’ ‘;返回 s; } 函数 C(obj,s=’’) { const map = new Map(Object.entries(obj)); for (let [key,value] of map) s+=key+‘->’+value + ’ ‘;返回 s; } function D(obj,s=’‘) { let o = { …obj, *Symbol.iterator { for (const i of Object.keys(this)) yield [i, this[i] ]; } } for (let [key,value] of o) s+=key+’->‘+value + ’ ‘;返回 s; } function E(obj,s=’’) { let o = { …obj, *Symbol.iterator {yield *Object.keys(this)} } for (let key of o) s+=key+ ‘->’+o[键] + ‘’;返回 s; } function F(obj,s=‘’) { for (let key of Object.keys(obj)) s+=key+‘->’+obj[key]+’ ‘;返回 s; } function G(obj,s=’‘) { for (let [key, value] of Object.entries(obj)) s+=key+’->‘+value+’ ‘;返回 s; } function H(obj,s=’‘) { for (let key of Object.getOwnPropertyNames(obj)) s+=key+’->‘+obj[key]+’ ‘;返回 s; } function I(obj,s=’‘) { for (Reflect.ownKeys(obj)的const key) s+=key+’->‘+obj[key]+’‘;返回 s; } 函数 J(obj,s=’‘) { 让键 = Object.keys(obj); for(let i = 0; i < keys.length; i++){ let key = keys[i]; s+=key+’->‘+obj[key]+’‘; } 返回 s; } 函数 K(obj,s=’‘) { var keys = Object.keys(obj), len = keys.length, i = 0; while (i < len) { 让键 = 键 [i]; s+=key+’->‘+obj[key]+’‘;我 += 1; } 返回 s; } function L(obj,s=’‘) { Object.keys(obj).forEach(key=> s+=key+’->‘+obj[key]+’ ’ );返回 s; } function M(obj,s=‘’) { Object.entries(obj).forEach(([key, value]) => s+=key+‘->’+value+’ ‘);返回 s; } function N(obj,s=’‘) { Object.getOwnPropertyNames(obj).forEach(key => s+=key+’->‘+obj[key]+’ ‘);返回 s; } 函数 O(obj,s=’‘) { Reflect.ownKeys(obj).forEach(key=> s+=key+’->‘+obj[key]+’ ’ );返回 s; } // 测试 var p = { “p1”: “value1”, “p2”: “value2”, “p3”: “value3” };让 log = (name,f) => console.log(${name} ${f(p)}
) log(‘A’,A);日志(‘B’,B);日志(‘C’,C);日志(‘D’,D);日志(‘E’,E);日志(‘F’,F);日志(‘G’,G);日志(‘H’,H);日志(‘我’,我);日志(‘J’,J);日志(‘K’,K);日志(‘L’,L);日志(‘M’,M);日志(‘N’,N);日志(‘O’,O);此代码段仅提供选定的解决方案
这是 chrome 上小物体的结果
https://i.stack.imgur.com/z8KJL.png
答9:
huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。
for(key in p) {
alert( p[key] );
}
注意:您可以对数组执行此操作,但您也将遍历 length 和其他属性。
当使用这样的 for 循环时,key 将只采用索引值,因此只会提醒 0、1、2 等...您需要访问 p[key]。
它是 JavaScript 中最慢的数组迭代方法。您可以在计算机上检查 - Best way to iterate over Arrays in JavaScript
@Pencroff:问题在于问题不在于循环遍历数组……;)
这是我在stackoverflow上不理解的东西。理查德给出了正确的答案,他是第一个给出这个答案的人,但他没有得到任何+1? @Bryan var p = {"p1":"q","p2":"w"}; for(key in p) { alert( key ); } 在警报中弹出“p1”和“p2”,那有什么问题???
我认为主要区别在于质量:其他答案不仅说明如何,而且说明注意事项(例如原型)以及如何处理这些注意事项。恕我直言,其他答案比我的要好:)。
答10:
huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。
由于 es2015 越来越受欢迎,我发布了这个答案,其中包括使用生成器和迭代器来平滑地遍历 [key, value] 对。就像在其他语言中一样,例如 Ruby。
好的,这是一个代码:
const MyObject = { ‘a’: ‘Hello’, ‘b’: ‘it’s’, ‘c’: ‘me’, ‘d’: ‘you’, ‘e’: ‘正在寻找’, ‘f’ : ‘for’, [Symbol.iterator]: function*() { for (const i of Object.keys(this)) { yield [i, this[i]]; } } }; for (const [k, v] of MyObject) { console.log(这里是键 ${k},这里是值 ${v}
); }
有关如何创建迭代器和生成器的所有信息,您可以在开发人员 Mozilla 页面上找到。
希望它对某人有所帮助。
编辑:
ES2017 将包含 Object.entries,这将使迭代对象中的 [key, value] 对更加容易。根据ts39阶段信息,现在已知它将成为标准的一部分。
我认为是时候更新我的答案,让它变得比现在更新鲜。
const MyObject = { ‘a’: ‘Hello’, ‘b’: ‘it’s’, ‘c’: ‘me’, ‘d’: ‘you’, ‘e’: ‘正在寻找’, ‘f’ : ‘为了’, }; for (const [k, v] of Object.entries(MyObject)) { console.log(这里是键 ${k},这里是值 ${v}
); }
您可以在 MDN 页面上找到有关使用情况的更多信息
这对我来说看起来完全多余/不需要。您会将它添加到系统中的每个对象中吗?我认为提供迭代器的目的是让您可以执行“for(const [k, v] of myObject)”。它只是看起来像额外的代码提供的额外价值很少。
答11:
huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。
在查看了这里的所有答案后,我自己的使用不需要 hasOwnProperty,因为我的 json 对象是干净的;添加任何额外的javascript处理真的没有意义。这就是我正在使用的所有内容:
for (var key in p) {
console.log(key + ' => ' + p[key]);
// key is key
// value is p[key]
}
JSON 对象是否干净无关紧要。如果在任何其他时间某些代码在 Object.prototype 上设置了一个属性,那么它将被 for..in 枚举。如果您确定没有使用任何执行此操作的库,则无需调用 hasOwnProperty。
如果使用 Object.create(null) 创建它可以完全干净
打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!