如何循环或枚举 JavaScript 对象?

问:

我有一个 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) 创建它可以完全干净

原文链接:https://www.huntsbot.com/qa/7QL4/how-do-i-loop-through-or-enumerate-a-javascript-object?lang=zh_CN&from=csdn

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值