ChatGPT解决这个技术问题 Extra ChatGPT

如何循环或枚举 JavaScript 对象?

我有一个 JavaScript 对象,如下所示:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

如何循环遍历 p 的所有元素(p1p2p3...)并获取它们的键和值?


K
Kostas Minaidis

您可以使用其他人所示的 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]) }

注意使用 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) 用于数组
感谢您的简单回答。它节省了我的时间。
T
T.J. Crowder

在 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 可以防止回调修改对象的键。
V
Vitim.us

您必须使用 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 是一种方法,而不是运算符,因此在任何对象中,它都可以替换为不同的函数,甚至是不是函数的值”
u
user229044

如果我们不提到循环对象的替代方法,这个问题就不会完整。

如今,许多著名的 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()更快,这些方法更容易使用,需要更少的编码并提供更好的错误处理。


获取值: $.each(obj, function (key, value) { console.log(value.title); });
有趣的是下划线和jquery如何更改参数:)
T
T.J. Crowder

前言:

对象属性可以是自己的(属性在对象本身上)或继承(不在对象本身上,在其原型之一上)。

对象属性可以是可枚举的或不可枚举的。不可枚举的属性被排除在许多属性枚举/数组之外。

属性名称可以是字符串或符号。名称为符号的属性被排除在许多属性枚举/数组之外。

在 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 之外的所有这些,您将在数组上使用某种循环构造(forfor-offorEach 等)。

例子:

for-in

// 要继承的原型对象,具有字符串命名的属性 const p = {answer: 42}; // 我们要查看的对象,它继承自 `p` const o = Object.create(p); // 一个字符串命名的属性 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(p); // 一个字符串命名的属性 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(p); // 一个字符串命名的属性 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(p); // 一个字符串命名的属性 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(p); // 一个字符串命名的属性 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(p); // 一个字符串命名的属性 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(p); // 一个字符串命名的属性 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(p); // 一个字符串命名的属性 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; }


很好地添加了可枚举/不可枚举的对象属性。
E
Eaten by a Grue

你可以像这样迭代它:

for (var key in p) {
  alert(p[key]);
}

请注意,key 不会采用属性的值,它只是一个索引值。


这是重复的,甚至不完全正确。您需要检查 hasOwnProperty 以使其正常工作
我最初根据上述评论对此表示反对,直到我意识到这个答案是第一位的,因此不是“重复的”。它可能不完整,但在许多情况下都可以正常工作。
P
Pencroff

在 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 上看到浏览器支持

对于旧浏览器,您有 simplefull polyfill

升级版:

perfjs.info 上此问题中所有最流行案例的性能比较:

object literal iteration


确实,我只是想发布此方法。但是你打败了我:(
K
Kamil Kiełczewski

表现

今天 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


K
Kristian
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”,那有什么问题???
我认为主要区别在于质量:其他答案不仅说明如何,而且说明注意事项(例如原型)以及如何处理这些注意事项。恕我直言,其他答案比我的要好:)。
R
Ran Marciano

由于 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)”。它只是看起来像额外的代码提供的额外价值很少。
F
Francis Lewis

在查看了这里的所有答案后,我自己的使用不需要 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) 创建它可以完全干净
s
strider

通过带有 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 函数可能会在一定程度上降低风险。
A
Akhil Ramani

单行和更具可读性的代码可以是..

Object.entries(myObject).map(([key, value]) => console.log(key, value))

很好的答案,它比上述解决方案更具可读性,但你能解释一下答案中的 .map(([key, value]) 发生了什么吗?
@Nivethan Object.entries 的输出将是一个数组数组。即 [ ['key1', 'value'], ['key2', 'value'] ] 因此,map 将遍历外部数组,每个数组元素一一传入其回调函数。所以,这里我使用了数组解构语法 ([key, value]) => {} 而不是 (element) => {},其中 element 是一个数组。
H
Hashbrown

有趣的是,这些答案中的人都触及了 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 直接使用在 Chrome 和 FF 中工作的花哨的 for...of
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]);

事实上,有了这个 shim,如果你仍然想利用 Map 的其他功能(而不是全部填充)但仍然想使用整洁的对象表示法,因为对象现在是可迭代的,你现在可以用它制作一个 Map!

//shown in demo
var realMap = new Map({well:'hello', there:'!'});

对于那些一般不喜欢 shim 或与 prototype 混淆的人,请随意在 window 上创建该函数,然后将其称为 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))

There's no reason why that wouldn't work.

欢迎来到未来。


Case in point。只要人们向下滚动并发现它有帮助,这就是最重要的。通常是我尝试做某事,不喜欢我在网上看到的东西,最终弄明白了,然后我回来分享。这很好,在谷歌搜索我完全忘记的事情之前,我实际上已经找到了自己的答案!
@HelpMeStackOverflowMyOnlyHope 就我个人而言,我不喜欢修改我自己没有定义的对象的原型。
@JanusTroelsen 您是否阅读了整个答案? 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ɐɹƆ? (PS 你的 SE 头像是老板)
O
Onera

您还可以使用 Object.keys() 并遍历对象键,如下所示:

var p = { "p1": "value1", "p2": "value2", "p3": "value3" }; Object.keys(p).forEach((key)=> { console.log(key +' -> '+ p[key]); });


你节省了我的时间,谢谢
很高兴知道:)
R
Ran Marciano

Object.keys() 上使用 for-of

喜欢:

让对象= {“key1”:“value1”,“key2”:“value2”,“key3”:“value3”}; for (let key of Object.keys(object)) { console.log(key + " : " + object[key]) }


T
TessavWalstijn

var p = { "p1": "value1", "p2": "value2", "p3": "value3" }; for (var key in p) { if (p.hasOwnProperty(key)) { console.log(key + " = " + p[key]); } }

输出:
p1 = values1
p2 = values2
p3 = values3


D
Dmitry Sheiko

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 ) ); } 返回文本; },CYCLES = 100000,obj = {},p1,p2,p3,键; // 使用随机属性填充对象 Array.apply( null, Array( CYCLES ) ).forEach(function(){ obj[ uniqid() ] = new Date() }); // 方法#1 p1 = performance.now(); Object.keys( obj ).forEach(function( key ){ var waste = obj[ key ]; }); p2 = 性能.now(); console.log("Object.keys 方法花费了 " + (p2 - p1) + " 毫秒。"); // 方法 #2 for( key in obj ) { if ( obj.hasOwnProperty( key ) ) { var waste = obj[ key ]; } } p3 = performance.now(); console.log("for...in/hasOwnProperty 方法花费了 " + (p3 - p2) + " 毫秒。");

在我的 Firefox 中,我有以下结果

Object.keys 方法耗时 40.21101451665163 毫秒。

for...in/hasOwnProperty 方法花费了 98.26163508463651 毫秒。

PS。在 Chrome 上差异更大http://codepen.io/dsheiko/pen/JdrqXa

PS2:在 ES6(EcmaScript 2015)中,您可以更好地迭代可迭代对象:

让 map = new Map().set('a', 1).set('b', 2); for (let pair of map) { console.log(pair); } // 或者让 map = new Map([ [false, 'no'], [true, 'yes'], ]); map.forEach((value, key) => { console.log(key, value); });


如果您不想放弃 {} 符号,您仍然可以使用 of without creating Maps
F
Flimm

在最新的 ES 脚本中,您可以执行以下操作:

让 p = {foo: "bar"}; for (let [key, value] of Object.entries(p)) { console.log(key, value); }


独立工作,但如果此函数为每个 for 条件返回一个值,则不起作用
P
Peter Mortensen

只有没有依赖关系的 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
}

M
Muhammad Usman

Object.keys() 方法返回给定对象自己的可枚举属性的数组。详细了解它here

var p = { "p1": "value1", "p2": "value2", "p3": "value3" }; Object.keys(p).map((key)=> console.log(key + "->" + p[key]))


H
Harsh Patel

这是另一种遍历对象的方法。

var p = { "p1": "value1", "p2": "value2", "p3": "value3" }; Object.keys(p).forEach(key => { console.log(key, p[key]) })


这很酷,但是对于大型对象,for 方法可能更高效。
a
akhtarvahid

在javascript中迭代对象的多种方法

使用 for...in 循环

var p = { "p1": "value1", "p2": "value2", "p3": "value3" }; for (let key in p){ if(p.hasOwnProperty(key)){ console.log(`${key} : ${p[key]}`) } }

使用 for...of 循环

var p = { "p1": "value1", "p2": "value2", "p3": "value3" }; for (let key of Object.keys(p)){ console.log(`key: ${key} & value: ${p[key]}`) }

forEach()Object.keysObject.valuesObject.entries 一起使用

var p = { "p1": "value1", "p2": "value2", "p3": "value3" }; Object.keys(p).forEach(key=>{ console.log(`${key} : ${p[key]}`); }); Object.values(p).forEach(value=>{ console.log(value); }); Object.entries(p).forEach(([key,value])=>{ console.log(`${key}:${value}`) })


N
Nicolas Bouvrette

使用纯 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

在这成为新标准之前,仍然可以使用旧方法,但在流行的库中也有替代方法,甚至 lightweight alternatives 对于那些不使用任何这些库的人。


你能提供这个工作的小提琴吗?这是我的尝试。 jsfiddle.net/abalter/sceeb211
@abalter 抱歉,我意识到我的代码中有错字。我修复了它并在此处更新了您的 JsFiddle:jsfiddle.net/sceeb211/2
我在 chrome 中并获得 Uncaught TypeError: Object.entries is not a function。它还没有在chrome中实现吗?
@abalter 是的。确保您拥有 Chrome 版本 51,并且您已按照我的编辑和 Jsfiddle 评论中的说明启用了该标志。您可以在此处查看详细信息:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
抱歉,我错过了关于国旗的内容。我看到它还不是一个完全实现的功能。
B
Biber

您可以为所有对象添加一个简单的 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 发生冲突,您可以使用您的唯一名称命名它。


修改内置对象的原型(如 Object)通常被认为是一种反模式,因为它很容易与其他代码发生冲突。所以伤口建议这样做。
A
AmerllicA

在可枚举的 JavaScript 对象上循环的一种好方法是使用 Object.keysObject.entriesmap 函数,这对于 ReactJS 来说可能很棒而且很常见。如下所示:

// assume items:

const items = {
  first: { name: 'phone', price: 400 },
  second: { name: 'tv', price: 300 },
  third: { name: 'sofa', price: 250 },
};

对于循环并在 ReactJS 上显示一些 UI,如下所示:

~~~
<div>
  {Object.entries(items).map(([key, ({ name, price })]) => (
    <div key={key}>
     <span>name: {name}</span>
     <span>price: {price}</span>
    </div>
  ))}
</div>

实际上,我使用了两次解构赋值,一次用于获取 key,一次用于获取 nameprice


我在使用 React 时正在寻找这个,以及 for 循环如何在 <Fragment> 中不起作用,这是完美的解决方案。非常感谢
亲爱的@Mob_Abominator,感谢您的甜言蜜语,我很高兴听到它对您有用。但我不明白 how for loops don't work inside <Fragment>。它仍然有任何问题吗?如果确实如此,请留下问题并告诉我,我会回答。如果什么都没有,你现在没事了。请给 this post of me 点赞。谢谢。
B
Bamieh

在 ES6 中,我们有众所周知的符号来公开一些以前的内部方法,您可以使用它来定义迭代器如何为该对象工作:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3",
    *[Symbol.iterator]() {
        yield *Object.keys(this);
    }
};

[...p] //["p1", "p2", "p3"]

这将给出与使用 for...in es6 循环相同的结果。

for(var key in p) {
    console.log(key);
}

但是了解您现在使用 es6 的能力很重要!


自定义对象迭代器调用由 Object.keys() 生成并在内存中分配的数组的内置数组迭代器......酷!
L
Lewis

我会这样做,而不是在每个 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");
}

y
yehonatan yehezkel

从 ES06 开始,您可以将对象的值作为数组获取

let arrValues = Object.values( yourObject) ;

它返回对象值的数组,而不是从原型中提取值!!

MDN DOCS Object.values()

和钥匙(在这里我已经回答了)

let arrKeys   = Object.keys(yourObject);

答案要求返回键和值的解决方案。
Z
Zakaria Acharki

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 [钥匙]); } } }


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]); } } }