如何通过JavaScript对象的键获取所有值?

7

我有一个JavaScript对象,其中包含一些键和值:

var obj = { 
    "key1" : "val1", 
    "key2" : "val2", 
    "key3" : "val3", 
    "key4" : ""
}

我希望能够遍历所有的键并获取它们对应的值。
我尝试了两种方法:
1)使用for(var key in keys)
var keys = Object.keys(obj);
for (var key in keys) {
    // ...
}

这种解决方案的问题在于keys对象是一个数组,所以我必须使用obj[keys[key]]]。 不太美观。
此外,检查"key4"时,返回值为"0"而不是""(空值)。
2)使用forEach。
Object.keys(obj).forEach(function(key){
    // ...
});

在这种情况下的问题是,如果我尝试执行以下操作:
Object.keys(obj).forEach(function(key){
    obj[key];  // <- obj is undefined !!
});

在foreach中,“obj”变量未定义!

迭代所有键以检索所有值的最佳方法是什么?

谢谢


@PranavCBalan 索引是第二个参数。https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach - jcubic
6个回答

10

只需使用for in

var obj = { 
  "key1" : "val1", 
  "key2" : "val2", 
  "key3" : "val3", 
  "key4" : ""
};

for (var key in obj) {

  console.log(key); // key1 and etc...
  console.log(obj[key]); // val1 and etc...
}

1
请注意,这是危险的,正如T.J. Crowder所说,因为它也会迭代任何继承的属性。例如,如果您执行Object.prototype.foo = "bar",它将迭代五次而不是四次。 - Amadan
你可以使用Object.hasOwnProperty()来保护这个for in循环,它会检查给定的属性是否不是继承而来的。 - Eduardo Melo

7
在你的第一个例子中,使用 for-in 循环遍历数组不是一个好的做法。如果要循环遍历数组,可以参考这个回答提供的多种方式。
如果想要循环遍历对象的所有键,可以使用 for-in对象 上进行操作:
for (var key in obj) {
    var value = obj[key];
    // ...
}

请注意,您将看到该对象的自己的属性,以及从其原型继承而来的属性。如果您只想要自己的属性,可以添加一个保护条件:
for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
        var value = obj[key];
        // ...
    }
}

...或者使用Object.keys(在2009年ES5中引入,因此不支持IE8;如果您需要支持像IE8这样的过时浏览器,可以使用shim):

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

在这两种情况下,您只会获得对象的可枚举属性。如果您需要包括不可枚举属性,请使用getOwnPropertyNames

Object.getOwnPropertyNames(obj).forEach(function(key) {
    var value = obj[key];
    // ...
});

这将获取对象自己的(非继承的)属性名称,即使它们是不可枚举的,只要它们是字符串(在ES5及之前版本中始终如此;在ES2015及以后版本中,它们通常是字符串,但如果您使用Symbol,则也可以是Symbol实例)。

getOwnPropertyNames也是在ES5中引入的,但我认为它无法模拟,因此您无法在IE8或其他过时的浏览器中使用它。


4

更新:

Object.values() 方法可能会有用。

另一种方法:

使用 ES6,Object.keys(obj).map(key => obj[key]) 将返回包含所有值的数组。


3

0

很奇怪你会遇到对象未定义的问题,这不应该发生。 除了其他答案之外,这里还有另一种方法。 只有在您不需要过滤任何内容并且只想拥有包含所有值(以及少量行)的数组时才有用。

var values = []
  Object.keys(object)
    .every( (prop) => values.push(object[prop]))

5
请在您的回答中添加解释。 - Lajos Arpad
3
"仅提供代码的回答对社区并不太有用。请查看[回答]." - JimHawkins

0

我更喜欢第一种方法,但没有必要单独存储键。让我们考虑这个例子:

function parseValues(obj, operation) {
    for (key in obj) {
        operation(obj[key], key);
    }
}

正如您所看到的,我们不需要读取键。您可以将像这样的函数用于任何目的。例如:

var myObject = {a: 1, b: 2, c: 3};

parseValues(myObject, function(item, key) {
    if (key !== "b") {
        if (item > 1) {
            myObject[key] = item * 2;
        }
    }
});

你可以用无数种方法来使用它。在第二种方法中,forEach 是对键而不是正在解析键的对象运行的。正如T.J.Crowther已经指出的那样,你需要使用 getOwnPropertyNames


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接