【问题标题】:How to get all properties values of a JavaScript Object (without knowing the keys)?如何获取 JavaScript 对象的所有属性值(不知道键)?
【发布时间】:2021-12-27 23:26:28
【问题描述】:

如果有 JavaScript 对象:

var objects={...};

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

【问题讨论】:

标签: javascript javascript-objects


【解决方案1】:

根据您必须支持的浏览器,这可以通过多种方式完成。绝大多数浏览器都支持 ECMAScript 5 (ES5),但请注意,下面的许多示例使用 Object.keys,这在 IE compatibility table。

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+(A.K.A. ES6)

使用 ECMAScript 2015 更容易迭代数组。在循环中逐个处理值时,您可以利用这一点:

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

使用 ECMAScript 2015 fat-arrow 函数,将对象映射到值数组变得单行:

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

// use vals array

ECMAScript 2015 引入了Symbol,其实例可用作属性名称。要获取要枚举的对象的符号,请使用Object.getOwnPropertySymbols(这个函数就是为什么Symbol 不能用于创建私有属性)。来自 ECMAScript 2015 的新 Reflect 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垫片

最后,正如 cmets 和 teh_senaus 在另一个答案中所指出的那样,将其中一个用作 shim 可能是值得的。不用担心,以下并没有改变原型,只是在Object 中添加了一个方法(危险性要小得多)。使用粗箭头函数,这也可以在一行中完成:

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

终于...

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

【讨论】:

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

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

for(var key in objects) {
    var value = objects[key];
}

【讨论】:

  • 小心被继承的原型对象的属性。参见:hasOwnProperty()
  • 如果你正在阅读这个答案,你应该肯定阅读the other one
  • 如果您正在阅读此答案并且您可能正在处理字符串,那么您绝对应该在脸上打 javascript。
  • 如果您阅读了上述答案并想打JavaScript,请尝试lodash
  • 应该指出这将不包括其enumerable 标志设置为false 的属性。这 - 除其他外 - 意味着您不会迭代任何类方法,但您将迭代以其他方式创建的方法。
【解决方案3】:

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

Object.values = function (obj) {
    var vals = [];
    for( var key in obj ) {
        if ( obj.hasOwnProperty(key) ) {
            vals.push(obj[key]);
        }
    }
    return vals;
}

【讨论】:

  • 修改 Object 不是什么大问题(Object.keys 是一个常见的 shim),您可能正在考虑修改 Object 原型。
  • 为什么需要使用hasOwnProperty() 进行测试?没有该属性的对象的循环中如何迭代键?
  • 谷歌@thomas,这很重要。它可能具有原型链中的属性。
【解决方案4】:

如果你可以访问 Underscore.js,你可以像这样使用_.values 函数:

_.values({one : 1, two : 2, three : 3}); // return [1, 2, 3]

【讨论】:

  • @MathieuAmiot -- 需要解释一下吗?
  • lodash 是一种兼容 api 的下划线替代品,一种(方式)更快的替代品。
  • @Paden 这是关于 SO 的相关问题:stackoverflow.com/questions/13789618/…
  • lodash 是不必要的,它会膨胀你的代码库
【解决方案5】:

ES5 Object.keys

var a = { a: 1, b: 2, c: 3 };
Object.keys(a).map(function(key){ return a[key] });
// result: [1,2,3]

【讨论】:

  • 为什么这被否决了?我会说这是最干净的解决方案之一。
  • 我不知道,为什么这被否决了。这是 js 中最简单、最纯粹的解决方案,无需使用任何库或任何其他实用程序。
  • @sanjeevshetty Object.values 是更简单的解决方案。
【解决方案6】:

如果你真的想要一个值数组,我发现这比用 for ... in 循环构建一个数组更干净。

ECMA 5.1+

function values(o) { return Object.keys(o).map(function(k){return o[k]}) }

值得注意的是,在大多数情况下,您并不真的需要一个值数组,这样做会更快:

for(var k in o) something(o[k]);

这会遍历 Object o 的键。在每次迭代中,将 k 设置为 o 的键。

【讨论】:

    【解决方案7】:

    你可以遍历键:

    foo = {one:1, two:2, three:3};
    for (key in foo){
        console.log("foo["+ key +"]="+ foo[key]);
    }
    

    将输出:

    foo[one]=1
    foo[two]=2
    foo[three]=3
    

    【讨论】:

    • 如果要避免继承属性,还需要检查`hasOwnProperty()'。
    【解决方案8】:

    ECMA2017 起:

    Object.values(obj) 会将所有属性值作为数组获取。

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Object/values

    【讨论】:

    • 应该注意这不会返回继承的属性。
    【解决方案9】:

    该问题没有指定是否还需要继承和不可枚举的属性。

    a question for getting everything, inherited properties and non-enumerable properties also,Google 无法轻易找到。

    如果我们要获取所有继承的和不可枚举的属性,我的解决方案是:

    function getAllPropertyNames(obj) {
        let result = new Set();
        while (obj) {
            Object.getOwnPropertyNames(obj).forEach(p => result.add(p));
            obj = Object.getPrototypeOf(obj);
        }
        return [...result];
    }
    

    然后遍历它们,只需使用 for-of 循​​环:

    function getAllPropertyNames(obj) {
      let result = new Set();
      while (obj) {
        Object.getOwnPropertyNames(obj).forEach(p => result.add(p));
        obj = Object.getPrototypeOf(obj);
      }
      return [...result];
    }
    
    let obj = {
      abc: 123,
      xyz: 1.234,
      foobar: "hello"
    };
    
    for (p of getAllPropertyNames(obj)) console.log(p);

    【讨论】:

      【解决方案10】:

      对于那些在 CofeeScript 时代早期适应的人,这里有另一个等价物。

      val for key,val of objects
      

      这可能比这更好,因为objects 可以简化为再次键入并降低可读性。

      objects[key] for key of objects
      

      【讨论】:

        【解决方案11】:

        显然 - 正如我最近了解到的 - 这是最快的方法:

        var objs = {...};
        var objKeys = Object.keys(obj);
        for (var i = 0, objLen = objKeys.length; i < objLen; i++) {
            // do whatever in here
            var obj = objs[objKeys[i]];
        }
        

        【讨论】:

        • 你能放一个codepen或jsfiddle这个例子吗?谢谢。
        【解决方案12】:

        使用以下 polyfill:

        if(!Object.values){Object.values=obj=>Object.keys(obj).map(key=>obj[key])}
        

        然后使用

        Object.values(my_object)
        

        3) 利润!

        【讨论】:

          【解决方案13】:

          const myObj = { a:1, b:2, c:3 }

          获取所有值:

          • 最短路径:

            • const myValues = Object.values(myObj)
          • const myValues = Object.keys(myObj).map(key =&gt; myObj[key])

          【讨论】:

          • 谢谢,这很好用。
          【解决方案14】:

          我意识到我来晚了,但这里有一个 shim 用于新的 firefox 47 Object.values 方法

          Object.prototype.values = Object.prototype.values || function(obj) {
            return this.keys(obj).map(function(key){
              return obj[key];
            });
          };
          

          【讨论】:

            【解决方案15】:

            Object.entries 做得更好。

              var dataObject = {"a":{"title":"shop"}, "b":{"title":"home"}}
             
               Object.entries(dataObject).map(itemArray => { 
                 console.log("key=", itemArray[0], "value=", itemArray[1])
              })

            【讨论】:

              【解决方案16】:

              使用:Object.values(),我们传入一个对象作为参数,并接收一个值数组作为返回值。

              这将返回给定对象自己的可枚举属性值的数组。您将获得与使用 for in 循环相同的值,但没有 Prototype 上的属性。这个例子可能会让事情更清楚:

              function person (name) {
                this.name = name;
              }
              
              person.prototype.age = 5;
              
              let dude = new person('dude');
              
              for(let prop in dude) {
                console.log(dude[prop]);     // for in still shows age because this is on the prototype
              }                              // we can use hasOwnProperty but this is not very elegant
              
              // ES6 + 
              console.log(Object.values(dude));
              // very concise and we don't show props on prototype

              【讨论】:

                【解决方案17】:
                const object1 = {
                  a: 'somestring',
                  b: 42
                };
                
                for (let [key, value] of Object.entries(object1)) {
                  console.log(`${key}: ${value}`);
                }
                
                // expected output:
                // "a: somestring"
                // "b: 42"
                // order is not guaranteed
                

                【讨论】:

                  【解决方案18】:

                  这里有个类似PHP的array_values()的函数

                  function array_values(input) {
                    var output = [], key = '';
                    for ( key in input ) { output[output.length] = input[key]; }
                    return output;
                  }
                  

                  如果您使用的是 ES6 或更高版本,以下是获取对象值的方法:

                  Array.from(values(obj));
                  

                  【讨论】:

                  • 由于某些原因 values() 在 Chrome 和 Firefox 中有效,但在 iojs/node 上无效。
                  【解决方案19】:

                  兼容 ES7,部分浏览器还不支持

                  因为,Object.values(&lt;object&gt;) 将被内置在 ES7 &

                  在等待所有浏览器支持它之前,你可以将它包装在一个函数中:

                  Object.vals=(o)=>(Object.values)?Object.values(o):Object.keys(o).map((k)=>o[k])
                  

                  然后:

                  Object.vals({lastname:'T',firstname:'A'})
                   // ['T','A']
                  

                  一旦浏览器与 ES7 兼容,您将无需更改代码中的任何内容。

                  【讨论】:

                    【解决方案20】:
                    var objects={...}; this.getAllvalues = function () {
                            var vls = [];
                            for (var key in objects) {
                                vls.push(objects[key]);
                            }
                            return vls;
                        }
                    

                    【讨论】:

                      【解决方案21】:

                      ECMAScript5中使用

                       keys = Object.keys(object);
                      

                      否则如果您的浏览器不支持,请使用众所周知的for..in loop

                      for (key in object) {
                          // your code here
                      }
                      

                      【讨论】:

                      • 问题是要求值,而不是键。
                      • @zachelrath 你是对的。 - 但是,如果您想获取值,则此脚本很有用,因为当您知道键时,您可以使用 object[key] 在循环中获取值。
                      • @fridojet 但这可以用for..in(和hasOwnProperty)来完成,所以它并没有真正获得任何东西..我希望ECMAScript 5th定义Object.pairs(和Object.items为@987654328 @),但可惜不是。
                      【解决方案22】:

                      现在我使用Dojo Toolkit,因为旧版浏览器不支持Object.values

                      require(['dojox/lang/functional/object'], function(Object) {
                          var obj = { key1: '1', key2: '2', key3: '3' };
                          var values = Object.values(obj);
                          console.log(values);
                      });
                      

                      输出:

                      ['1', '2', '3']
                      

                      【讨论】:

                      • 严格来说,数组是不正确的。你有一个字符串数组而不是一个数字数组。
                      【解决方案23】:

                      使用

                      console.log(variable)
                      

                      如果您使用 google chrome 打开控制台,请使用 Ctrl+Shift+j

                      转到 >> 控制台

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2016-08-21
                        • 2012-01-28
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多