如何获取 JavaScript 对象的所有属性值(不知道键)?

IT技术 javascript javascript-objects
2021-02-08 04:22:48

如果有一个 JavaScript 对象:

var objects={...};

假设,它有 50 多个属性,不知道属性名称(即不知道“键”)如何在循环中获取每个属性值?

6个回答

根据您必须支持的浏览器,这可以通过多种方式完成。绝大多数浏览器都支持 ECMAScript 5 (ES5),但请注意,下面的许多示例都使用Object.keys了 IE < 9 中不可用的 。请参阅兼容性表

ECMAScript 3+

如果您必须支持旧版本的 IE,那么这是您的选择:

for (var key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
        var val = obj[key];
        // use val
    }
}

嵌套if确保您不会枚举对象原型链中的属性(这几乎肯定是您想要的行为)。你必须使用

Object.prototype.hasOwnProperty.call(obj, key) // ok

而不是

obj.hasOwnProperty(key) // bad

因为 ECMAScript 5+ 允许您使用 来创建无原型对象Object.create(null),而这些对象将没有该hasOwnProperty方法。顽皮的代码也可能产生覆盖该hasOwnProperty方法的对象

ECMAScript 5+

您可以在任何支持 ECMAScript 5 及更高版本的浏览器中使用这些方法。这些从对象中获取值并避免在原型链上进行枚举。obj你的对象在哪里

var keys = Object.keys(obj);

for (var i = 0; i < keys.length; i++) {
    var val = obj[keys[i]];
    // use val
}

如果你想要更紧凑的东西或者你想要小心循环中的函数,那么Array.prototype.forEach你的朋友:

Object.keys(obj).forEach(function (key) {
    var val = obj[key];
    // use val
});

下一个方法构建一个包含对象值的数组。这便于循环。

var vals = Object.keys(obj).map(function (key) {
    return obj[key];
});

// use vals array

如果你想让那些使用Object.keys安全null(按原样for-in),那么你可以做Object.keys(obj || {})....

Object.keys返回可枚举的属性。对于迭代简单的对象,这通常就足够了。如果您在使用非枚举的属性,你需要工作的东西,你可以使用Object.getOwnPropertyNames代替Object.keys

ECMAScript 2015+(又名 ES6)

使用 ECMAScript 2015 更容易迭代数组。在循环中逐个处理值时,您可以利用它来发挥自己的优势:

for (const key of Object.keys(obj)) {
    const val = obj[key];
    // use val
}

使用 ECMAScript 2015 粗箭头函数,将对象映射到值数组成为单行:

const vals = Object.keys(obj).map(key => obj[key]);

// use vals array

ECMAScript 2015 引入了Symbol,其实例可用作属性名称。要获取要枚举的对象的符号,请使用Object.getOwnPropertySymbols(此函数是为什么Symbol 不能用于创建私有属性的原因)。ReflectECMAScript 2015的新API 提供了Reflect.ownKeys,它返回属性名称(包括不可枚举的)和符号的列表。

数组推导式(不要尝试使用)

数组推导式在发布前已从 ECMAScript 6删除在删除之前,解决方案如下所示:

const vals = [for (key of Object.keys(obj)) obj[key]];

// use vals array

ECMAScript 2017+

ECMAScript 2016 添加了不影响本主题的功能。ECMAScript 2017 规范添加了Object.valuesObject.entries. 两个都返回数组(考虑到与 的类比,这会让某些人感到惊讶Array.entries)。Object.values可以按原样使用或与for-of循环一起使用

const values = Object.values(obj);

// use values array or:

for (const val of Object.values(obj)) {
    // use val
}

如果您想同时使用键和值,那么Object.entries适合您。它产生一个充满[key, value]的数组您可以按原样使用它,或者(还请注意 ECMAScript 2015 解构赋值)在for-of循环中使用:

for (const [key, val] of Object.entries(obj)) {
    // use key and val
}

Object.values 垫片

最后,正如评论中和 teh_senaus 在另一个答案中所指出的,使用其中一个作为垫片可能是值得的。不用担心,下面没有改变原型,它只是添加了一个方法Object(危险性要小得多)。使用 fat-arrow 函数,这也可以在一行中完成:

Object.values = obj => Object.keys(obj).map(key => obj[key]);

你现在可以使用像

// ['one', 'two', 'three']
var values = Object.values({ a: 'one', b: 'two', c: 'three' });

如果您想在本地Object.values存在时避免填充,则可以执行以下操作:

Object.values = Object.values || (obj => Object.keys(obj).map(key => obj[key]));

最后...

请注意您需要支持的浏览器/版本。在实现方法或语言功能的地方,以上是正确的。例如,直到最近,V8 才默认关闭对 ECMAScript 2015 的支持,这为 Chrome 等浏览器提供了动力。在您打算支持的浏览器实现您需要的功能之前,应避免使用 ECMAScript 2015 中的功能。如果您使用babel将代码编译为 ECMAScript 5,那么您就可以访问此答案中的所有功能。

遗憾的是,在所有所谓的技巧中,我们还需要提及obj两次。我想创建一个辅助函数是不可避免的?类似于 values(obj) 的东西。
2021-03-13 04:22:48
我无法想象为什么我们必须等待 ES2017 才能获得 Object.values() 方法。
2021-03-14 04:22:48
这些方法中的任何一种都可以用作垫片。例如:Object.values = obj => Object.keys(obj).map(key => obj[key]);
2021-03-25 04:22:48
这应该是公认的(或至少更多赞成的)答案,因为接受的答案不完整(@olive 指出了这一点)。
2021-04-02 04:22:48
ECMA 5 解决方案应该适用于所有现代浏览器。ECMA 6 尚未最终确定,所有浏览器的支持都是初步的。在 Chrome 中,ECMA 6 部分实现但被禁用。在 Firefox 中,支持更好,但数组理解是错误的(如上所述)。我认为我使用将来时会暗示这一点。@JacekLampart,哪个解决方案给了你错误?
2021-04-06 04:22:48

通过使用一个简单的for..in循环:

for(var key in objects) {
    var value = objects[key];
}
可能应该指出,这不包括将enumerable标志设置为 false 的属性这 - 除其他外 - 意味着您不会迭代任何类方法,但您将迭代以其他方式创建的方法。
2021-03-13 04:22:48
如果你正在阅读这个答案,你绝对应该阅读另一个
2021-03-28 04:22:48
小心被继承的原型对象的属性。请参阅:hasOwnProperty()
2021-03-29 04:22:48
如果您正在阅读这个答案并且您可能正在处理字符串,那么您绝对应该在脸上打 javascript。
2021-03-29 04:22:48
如果您阅读了上面的答案并想在脸上打 JavaScript,请尝试lodash
2021-04-03 04:22:48

这是一个可重用的函数,用于将值放入数组中。它也考虑到原型。

Object.values = function (obj) {
    var vals = [];
    for( var key in obj ) {
        if ( obj.hasOwnProperty(key) ) {
            vals.push(obj[key]);
        }
    }
    return vals;
}
为什么需要测试hasOwnProperty()如何在该对象的循环内迭代该键还没有获得该属性?
2021-03-23 04:22:48
修改Object不是什么大问题(Object.keys是一个常见的垫片),您可能正在考虑修改 Object 原型。
2021-03-24 04:22:48
谷歌它@thomas,这很重要。它可能具有来自其原型链的属性。
2021-03-27 04:22:48

如果您有权访问 Underscore.js,则可以使用如下_.values函数:

_.values({one : 1, two : 2, three : 3}); // return [1, 2, 3]
@MathieuAmiot——想解释一下吗?
2021-03-18 04:22:48
lodash 是一种 api 兼容的下划线替代品,一种(方式)更快的替代品。
2021-03-21 04:22:48
@Paden 这里有一个关于 SO 的相关问题:stackoverflow.com/questions/13789618/...
2021-03-31 04:22:48
lodash 是不必要的,会膨胀你的代码库
2021-04-01 04:22:48

ES5 Object.keys

var a = { a: 1, b: 2, c: 3 };
Object.keys(a).map(function(key){ return a[key] });
// result: [1,2,3]
为什么这被否决了?我会说这是最干净的解决方案之一。
2021-03-13 04:22:48
我不知道,为什么这被否决了。这是 js 中最简单、最纯粹的解决方案,无需使用任何库或任何其他实用程序。
2021-03-22 04:22:48
@sanjeevshettyObject.values是更简单的解决方案。
2021-03-26 04:22:48