如何循环或枚举 JavaScript 对象?

IT技术 javascript loops for-loop each
2020-12-23 22:50:20

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

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

现在我想遍历所有p元素 ( p1, p2, p3...) 并获取它们的键和值。我怎样才能做到这一点?

如有必要,我可以修改 JavaScript 对象。我的最终目标是遍历一些键值对,如果可能,我想避免使用eval.

6个回答

您可以使用for-in其他人显示循环。但是,您还必须确保获得的密钥是对象的实际属性,而不是来自原型。

这是片段:

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

for (var key in p) {
    if (p.hasOwnProperty(key)) {
        console.log(key + " -> " + p[key]);
    }
}

For-of 与 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}`);
}
实际上,For...in并没有被弃用。 对于每个...in是。但我真的很喜欢考古学家这个词......我将不得不开始使用它。
2021-02-06 22:50:20
(for..in) 用于对象,(for.. of) 用于数组
2021-02-07 22:50:20
在 javascript 中,每个对象都有一堆具有元信息的内置键值对。当您遍历对象的所有键值对时,您也在遍历它们。hasOwnPropery() 过滤掉这些。
2021-02-09 22:50:20
如何添加循环的值?谢谢
2021-02-13 22:50:20

在 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防止回调修改对象的键。
2021-03-05 22:50:20

你必须使用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什么不是。但我想这只是一个意见问题:)
2021-02-11 22:50:20
是的,我更喜欢保留{ }主要是为了避免混淆,如果以后需要向if范围添加一些东西
2021-02-11 22:50:20
这比 levik 的解决方案要好,因为它允许主逻辑只有一个嵌套循环,而不是两个;使代码更易于阅读。虽然我会松开继续周围的括号;它们是多余的。
2021-02-13 22:50:20
阅读我之前的评论,我意识到我没有使用正确的术语,因为我说的是“if scope”;但请记住,JavaScript 只有函数作用域。所以我真正的意思是“if block”。
2021-02-19 22:50:20
“不幸的是,hasOwnProperty 是一种方法,而不是运算符,因此在任何对象中,它都可以用不同的函数甚至不是函数的值替换”
2021-03-08 22:50:20

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

现在,许多著名的 JavaScript 库都提供了自己的方法来迭代集合,即遍历数组对象和类数组对象这些方法使用方便,并且与任何浏览器完全兼容。

  1. 如果您使用jQuery,则可以使用jQuery.each()方法。它可用于无缝迭代对象和数组:

    $.each(obj, function(key, value) {
        console.log(key, value);
    });
    
  2. Underscore.js 中,您可以找到 method _.each(),它遍历元素列表,依次将每个元素生成为提供的函数(注意iteratee函数中的参数顺序!):

    _.each(obj, function(value, key) {
        console.log(key, value);
    });
    
  3. Lo-Dash提供了几种迭代对象属性的方法。Basic _.forEach()(或它的 alias _.each())对于循环遍历对象和数组很有用,但是(!)具有length属性的对象被视为数组,并且为了避免这种行为,建议使用_.forIn()_.forOwn()方法(这些也有value参数首先出现):

    _.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); });
2021-02-08 22:50:20
有趣的是,underscore 和 jquery 如何更改参数:)
2021-02-19 22:50:20

前言:

  • 对象属性可以是自己的(属性在对象本身上)或继承的(不是在对象本身上,而是在其原型之一上)。
  • 对象属性可以是可枚举的不可枚举的不可枚举的属性被排除在许多属性枚举/数组之外。
  • 属性名称可以是字符串或符号。名称为 Symbols 的属性被排除在许多属性枚举/数组之外。

在 2018 年,您循环访问对象属性的选项是(列表后面的一些示例):

  1. for-in[ MDN , spec ] — 一种循环结构,循环遍历对象的可枚举属性的名称,包括继承的名称为字符串的属性
  2. Object.keys[ MDN规格] -提供一个对象的名称的数组的函数自己的枚举的性质,其名称是字符串。
  3. Object.values[ MDN规格] -甲函数提供所述的阵列的对象的的自己的枚举的属性。
  4. Object.entries[ MDN规格] -提供所述名称的数组的函数一个对象的值自身可枚举属性(阵列中的每个条目是[name, value]阵列)。
  5. Object.getOwnPropertyNames[ MDN , spec ] — 一个函数,提供名称为字符串的对象自身属性(甚至不可枚举的)的名称数组
  6. Object.getOwnPropertySymbols[ MDN , spec ] — 一个函数,提供名称为 Symbols的对象自身属性(甚至不可枚举的)的名称数组
  7. Reflect.ownKeys[ MDN , spec ] — 一个函数,提供对象自身属性(甚至不可枚举的)的名称数组,无论这些名称是字符串还是符号。
  8. 如果您想要一个对象的所有属性,包括不可枚举的继承属性,您需要使用循环和Object.getPrototypeOf[ MDN , spec ] 并在原型链中的每个对象上使用Object.getOwnPropertyNames, Object.getOwnPropertySymbols, 或Reflect.ownKeys(此答案底部的示例)。

随着所有这些硬盘中for-in,你会使用某种类型的阵列上的循环结构(中forfor-offorEach,等)。

例子:

for-in

Object.keys (使用for-of循环,但您可以使用任何循环构造)

Object.values

Object.entries

Object.getOwnPropertyNames

Object.getOwnPropertySymbols

Reflect.ownKeys

所有属性,包括继承的不可枚举的:

很好地添加了可枚举/不可枚举的对象属性。
2021-03-02 22:50:20