【问题标题】:How to list the properties of a JavaScript object?如何列出 JavaScript 对象的属性?
【发布时间】:2010-09-17 12:08:09
【问题描述】:

假设我这样创建了一个对象:

var myObject =
        {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};

检索属性名称列表的最佳方法是什么?即我想最终得到一些可变的“键”:

keys == ["ircEvent", "method", "regex"]

【问题讨论】:

  • 有点离题,但如果你使用 underscore.js:_.keys(myJSONObject)
  • TL;DR: 如果您只需要可枚举的属性:Object.keys(obj) 有时您也需要不可枚举的属性。如果你这样做,请务必记住这一点!要获取它们,请使用 Object.getOwnPropertyNames(obj) stackoverflow.com/a/32413145/1599699

标签: javascript


【解决方案1】:

在现代浏览器(IE9+、FF4+、Chrome5+、Opera12+、Safari5+)中,您可以使用内置的Object.keys 方法:

var keys = Object.keys(myObject);

上面有一个完整的 polyfill,但一个简化的版本是:

var getKeys = function(obj){
   var keys = [];
   for(var key in obj){
      keys.push(key);
   }
   return keys;
}

或者将var getKeys 替换为Object.prototype.keys 以允许您在任何对象上调用.keys()。扩展原型有一些副作用,我不建议这样做。

【讨论】:

  • 我会再次更新,大意是“您可能很想对对象原型执行此操作……但不要这样做!”
  • 有人要开灯吗,为什么不建议在Object的原型中添加函数?
  • 这本身就是一个完全不同的问题,在 stackoverflow 或谷歌上快速搜索会让你有很多阅读内容
  • for (var key in myObject) {...} 技术对于浏览器和 V8 之外的 javascript 运行时很有用。例如,当将 javascript map-reduce 查询传递给 Riak 时,Object 对象不存在,因此 Object.keys 方法不可用。
  • @slashnick 您的“简化版本”返回对象原型链中的所有属性(因为它使用“for ... in”),而(ECMAScript 5.1)Object.keys 方法只返回对象自身的属性。我认为这是一个重要的区别。
【解决方案2】:

正如slashnick 所指出的,您可以使用“for in”构造来遍历对象以获取其属性名称。但是,您将遍历对象原型链中的所有属性名称。如果您想迭代对象自身的属性,您可以使用Object#hasOwnProperty() 方法。因此具有以下内容。

for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
        /* useful code here */
    }
}

【讨论】:

  • 我希望我在上面 slashnic 的回答之前读过这个。我只需要花 15 分钟按住 esc 键,因为该对象有大约一百万个属性,其中大部分没有使用,而且我有一个警报。
  • 这是 Zakas 本人关于该主题的出色文章:nczonline.net/blog/2010/07/27/…
  • LOL @MarkHenderson - 但下一次,只需终止浏览器的进程并重新启动它,而不是浪费 15 分钟 :)
  • 一个相关的函数是 obj.getOwnPropertyNames() - developer.mozilla.org/en-US/docs/JavaScript/Reference/…
  • @MarkHenderson 你为什么不使用console.log?
【解决方案3】:

IE 不支持原生属性的 for(i in obj)。这是我能找到的所有道具的列表。

似乎 stackoverflow 做了一些愚蠢的过滤。

该列表位于此 google 群组帖子的底部:- https://groups.google.com/group/hackvertor/browse_thread/thread/a9ba81ca642a63e0

【讨论】:

    【解决方案4】:

    【讨论】:

    • +1 因为我来到这里的目的是构建类似的东西(尽管不是那么好)。
    • netgrow.com.au/assets/files/dump/dump.zip not found 如何下载转储javascript?
    • @Kiquenet 每次我想构建这样的东西时,我都会选择常规的对象检查器,如果你想用 HTML 呈现它,可以使用 npm modules 之类的东西。坦率地说,让我陷入困境的是,我想要比图片上的更好的东西,但从未设法将其概念化。在检查器中浏览对象很糟糕,但是尝试从任意对象中推断出含义的启发式方法(例如,将对象数组分类到带有列的表中)在实践中并不总是有效。
    • 关于 Pretty Print Javascript https://j11y.io/demos/prettyprint/ 是什么?
    【解决方案5】:

    请注意,Firefox 4、Chrome 6、Safari 5、IE 9 及更高版本支持 Object.keys 和其他 ECMAScript 5 方法。

    例如:

    var o = {"foo": 1, "bar": 2}; 
    alert(Object.keys(o));
    

    ECMAScript 5 兼容性表:http://kangax.github.com/es5-compat-table/

    新方法说明:http://markcaudill.com/index.php/2009/04/javascript-new-features-ecma5/

    【讨论】:

    【解决方案6】:

    正如 Sam Dutton 所回答的,ECMAScript 第 5 版中引入了一种用于此目的的新方法。 Object.keys() 会做你想做的事,并在Firefox 4、Chrome 6、Safari 5 和IE 9 中得到支持。

    您也可以在不支持该方法的浏览器中轻松实现该方法。但是,那里的一些实现与 Internet Explorer 不完全兼容。这是一个更兼容的解决方案:

    Object.keys = Object.keys || (function () {
        var hasOwnProperty = Object.prototype.hasOwnProperty,
            hasDontEnumBug = !{toString:null}.propertyIsEnumerable("toString"),
            DontEnums = [ 
                'toString', 'toLocaleString', 'valueOf', 'hasOwnProperty',
                'isPrototypeOf', 'propertyIsEnumerable', 'constructor'
            ],
            DontEnumsLength = DontEnums.length;
            
        return function (o) {
            if (typeof o != "object" && typeof o != "function" || o === null)
                throw new TypeError("Object.keys called on a non-object");
        
            var result = [];
            for (var name in o) {
                if (hasOwnProperty.call(o, name))
                    result.push(name);
            }
        
            if (hasDontEnumBug) {
                for (var i = 0; i < DontEnumsLength; i++) {
                    if (hasOwnProperty.call(o, DontEnums[i]))
                        result.push(DontEnums[i]);
                }   
            }
        
            return result;
        };
    })();
    

    请注意,当前接受的答案不包括对 hasOwnProperty() 的检查,并且将返回通过原型链继承的属性。它也没有解释 Internet Explorer 中著名的 DontEnum 错误,即原型链上的不可枚举属性导致本地声明的同名属性继承其 DontEnum 属性。

    实施 Object.keys() 将为您提供更强大的解决方案。

    编辑:在最近与 Prototype 的知名贡献者 kangax 讨论之后,我根据找到的 Object.forIn() 函数的代码实现了 DontEnum 错误的解决方法here .

    【讨论】:

    • 很好的答案,我认为接受的答案仍然是最准确的解决方案,假设它总是一个 JSON 字典。这肯定是在其他地方使用的。
    • @David Caunt:谢谢 :-) 不幸的是,接受的答案仍然会与 DontEnum 错误相冲突,而且您永远不知道 JSON 对象可能具有像“valueOf”或“constructor”这样的字符串作为一个它的钥匙。它还将迭代对Object.prototype 的扩展。但是,通常情况下,较短的代码看起来比更大、更健壮的代码更具吸引力,但这个答案的重点是使用 ECMAScript 5th 的 Object.keys(),它可以在不支持它的浏览器中实现代码。原生版本的性能会比这更好。
    • 非常好,Andy :) 我想提醒一下——似乎没有人在这个帖子中提到——ES5 Object.keys 只返回对应于 enumerable的字符串数组> 对象的属性。这在使用本地(用户定义的)对象时可能并不重要,但对于宿主对象应该非常明显(尽管未指定的宿主对象行为是一个单独的——痛苦的——故事)。为了枚举所有(包括不可枚举的)属性,ES5 提供了Object.getOwnPropertyNames(在我的兼容表中查看它的支持——kangax.github.com/es5-compat-table
    • 我已将此解决方案集成到 es5-shim github.com/kriskowal/es5-shim/blob/master/es5-shim.js#L390
    • 有人能解释一下为什么这是Object.keys(stuff)而不是stuff.keys()吗?
    【解决方案7】:

    如果您只尝试获取元素而不是函数,那么此代码可以帮助您

    this.getKeys = function() {
    
        var keys = new Array();
        for(var key in this) {
    
            if( typeof this[key] !== 'function') {
    
                keys.push(key);
            }
        }
        return keys;
    }
    

    这是我的 HashMap 实现的一部分,我只想要键,“this”是包含键的 hashmap 对象

    【讨论】:

      【解决方案8】:

      这适用于大多数浏览器,甚至在 IE8 中,并且不需要任何类型的库。 var i 是您的密钥。

      var myJSONObject =  {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"}; 
      var keys=[];
      for (var i in myJSONObject ) { keys.push(i); }
      alert(keys);
      

      【讨论】:

      • 您的回答与已经发布的类似,还有什么要补充的吗?
      【解决方案9】:

      在支持js 1.8的浏览器下:

      [i for(i in obj)]
      

      【讨论】:

        【解决方案10】:

        可以用 jQuery 做如下:

        var objectKeys = $.map(object, function(value, key) {
          return key;
        });
        

        【讨论】:

          【解决方案11】:

          Mozilla 有 full implementation details 说明如何在不支持的浏览器中执行此操作,如果有帮助的话:

          if (!Object.keys) {
            Object.keys = (function () {
              var hasOwnProperty = Object.prototype.hasOwnProperty,
                  hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
                  dontEnums = [
                    'toString',
                    'toLocaleString',
                    'valueOf',
                    'hasOwnProperty',
                    'isPrototypeOf',
                    'propertyIsEnumerable',
                    'constructor'
                  ],
                  dontEnumsLength = dontEnums.length;
          
              return function (obj) {
                if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) throw new TypeError('Object.keys called on non-object');
          
                var result = [];
          
                for (var prop in obj) {
                  if (hasOwnProperty.call(obj, prop)) result.push(prop);
                }
          
                if (hasDontEnumBug) {
                  for (var i=0; i < dontEnumsLength; i++) {
                    if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]);
                  }
                }
                return result;
              };
            })();
          }
          

          您可以随意包含它,但也可以包含在脚本堆栈顶部的某种extensions.js 文件中。

          【讨论】:

          • MDN 实现是基于 Andy E 的,它已经作为答案给出。
          【解决方案12】:

          基于已接受的答案。

          如果对象有你想调用的属性说 .properties() 试试!

          var keys = Object.keys(myJSONObject);
          
          for (var j=0; j < keys.length; j++) {
            Object[keys[j]].properties();
          }
          

          【讨论】:

            【解决方案13】:

            由于我几乎在每个项目中都使用 underscore.js,所以我会使用 keys 函数:

            var obj = {name: 'gach', hello: 'world'};
            console.log(_.keys(obj));
            

            输出将是:

            ['name', 'hello']
            

            【讨论】:

            【解决方案14】:

            Object.getOwnPropertyNames(obj)

            除了Object.keys(obj) 显示的属性之外,此函数还显示不可枚举的属性。

            在 JS 中,每个属性都有几个属性,包括一个布尔值 enumerable

            一般来说,不可枚举的属性更“内部化”且使用频率较低,但有时深入了解它们以了解实际情况。

            例子:

            var o = Object.create({base:0})
            Object.defineProperty(o, 'yes', {enumerable: true})
            Object.defineProperty(o, 'not', {enumerable: false})
            
            console.log(Object.getOwnPropertyNames(o))
            // [ 'yes', 'not' ]
            
            console.log(Object.keys(o))
            // [ 'yes' ]
            
            for (var x in o)
                console.log(x)
            // yes, base
            

            还要注意如何:

            • Object.getOwnPropertyNamesObject.keys 不要沿着原型链找到base
            • for in

            更多关于原型链的信息在这里:https://stackoverflow.com/a/23877420/895245

            【讨论】:

              【解决方案15】:

              该解决方案适用于我的案例和跨浏览器:

              var getKeys = function(obj) {
                  var type = typeof  obj;
                  var isObjectType = type === 'function' || type === 'object' || !!obj;
              
                  // 1
                  if(isObjectType) {
                      return Object.keys(obj);
                  }
              
                  // 2
                  var keys = [];
                  for(var i in obj) {
                      if(obj.hasOwnProperty(i)) {
                          keys.push(i)
                      }
                  }
                  if(keys.length) {
                      return keys;
                  }
              
                  // 3 - bug for ie9 <
                  var hasEnumbug = !{toString: null}.propertyIsEnumerable('toString');
                  if(hasEnumbug) {
                      var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
                          'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
              
                      var nonEnumIdx = nonEnumerableProps.length;
              
                      while (nonEnumIdx--) {
                          var prop = nonEnumerableProps[nonEnumIdx];
                          if (Object.prototype.hasOwnProperty.call(obj, prop)) {
                              keys.push(prop);
                          }
                      }
              
                  }
              
                  return keys;
              };
              

              【讨论】:

                【解决方案16】:

                使用Reflect.ownKeys()

                var obj = {a: 1, b: 2, c: 3};
                Reflect.ownKeys(obj) // ["a", "b", "c"]
                

                Object.keysObject.getOwnPropertyNames 无法获得 non-enumerable 属性。它甚至适用于不可枚举的属性。

                var obj = {a: 1, b: 2, c: 3};
                obj[Symbol()] = 4;
                Reflect.ownKeys(obj) // ["a", "b", "c", Symbol()]
                

                【讨论】:

                  【解决方案17】:

                  使用 ES6 及更高版本(ECMAScript 2015),您可以像这样获取所有属性:

                  let keys = Object.keys(myObject);
                  

                  如果你想列出所有值:

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

                  【讨论】:

                    【解决方案18】:

                    这里有很多答案...这是我的 2 美分。

                    我需要一些东西来打印出所有 JSON 属性,即使是带有子对象或数组(包括父名称)的那些。

                    所以 - 对于这个 JSON:

                    mylittleJson = {
                      "one": "blah",
                      "two": {
                          "twoone": "",
                          "twotwo": "",
                          "twothree": ['blah', 'blah']
                      },
                      "three": ""
                    }
                    

                    它会打印这个:

                    .one
                    .two.twoone
                    .two.twotwo
                    .two.twothree
                    .three
                    

                    这里是函数

                    function listatts(parent, currentJson){
                       var attList = []
                       if (typeof currentJson !== 'object' || currentJson == undefined || currentJson.length > 0) {
                          return
                       }
                       for(var attributename in currentJson){
                           if (Object.prototype.hasOwnProperty.call(currentJson, attributename)) {
                               childAtts = listatts(parent + "." + attributename, currentJson[attributename])
                               if (childAtts != undefined && childAtts.length > 0)
                                   attList = [...attList, ...childAtts]
                               else 
                                   attList.push(parent + "." + attributename)
                           }
                       }
                       return attList
                    }
                    

                    希望它也有帮助。

                    【讨论】:

                      猜你喜欢
                      • 2018-02-07
                      • 2015-07-21
                      • 2011-11-07
                      • 1970-01-01
                      • 1970-01-01
                      • 2019-05-22
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多