如何列出JavaScript对象的属性?


841

说我这样创建一个对象:

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

检索属性名称列表的最佳方法是什么?即我想以一些变量“键”结束:

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

3
话题有点偏离,但是如果您使用underscore.js:_.keys(myJSONObject)
Endy Tjahjono

Answers:


1075

在现代浏览器(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 getKeysObject.prototype.keys以允许您调用.keys()任何对象。扩展原型会带来一些副作用,我不建议您这样做。


17
我将再次更新为“您可能会想这样做来反对原型……但不要这样做!”
AnthonyWJones

4
有人想公开一下,为什么不建议在Object原型中添加功能?
Vishwanath 2012年

2
这本身就是一个完全不同的问题,在stackoverflow或google上进行快速搜索将为您提供大量阅读资源
ximi

3
for (var key in myObject) {...}技术对于浏览器和V8之外的javascript运行时很有用。例如,将javascript map-reduce查询传递给Riak时,该Object对象不存在,因此该Object.keys方法不可用。
ekillaby

19
@slashnick您的“简化版本”返回对象原型链中的所有属性(因为它使用的是“ for ... in”),而(ECMAScript 5.1)Object.keys方法仅返回对象自身的属性。我认为这是一个重要的区别。
马丁·卡雷尔

255

正如slashnick指出的那样,您可以使用“ for in”构造来遍历对象的属性名称。但是,您将遍历对象原型链中的所有属性名称。如果你想迭代只是在对象自己的属性,你可以利用的对象#hasOwnProperty()方法。因此具有以下。

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

25
我希望我在以上斜杠的答案之前已经读过这篇文章。我只需要花15分钟按住esc键,因为该对象具有大约一百万个属性,其中大多数未使用,并且对此我发出了警报。
马克·亨德森

这里是由Zakas自己主题的外观极好文章:nczonline.net/blog/2010/07/27/...
卡夫雷拉

4
大声笑@MarkHenderson-但下一次,只是杀死浏览器的进程并重新启动它,而不是浪费15分钟:)
JD Smith

一个相关的功能是obj.getOwnPropertyNames()- developer.mozilla.org/en-US/docs/JavaScript/Reference/…–
Steve Goodman

@MarkHenderson为什么不使用console.log?
LasagnaAndroid 2014年

102

正如Sam Dutton回答的那样,ECMAScript 5th Edition中引入了用于此目的的新方法。 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错误的解决方法。


好的答案,我认为公认的答案始终是性能最高的准确解决方案,假设它始终是JSON字典。这肯定是在其他地方使用的那个。
David Snabel-Caunt 2010年

1
@David Caunt:谢谢:-)不幸的是,被接受的答案仍然会与DontEnum错误发生冲突,并且您永远不知道哪个JSON对象可能将诸如“ valueOf”或“ constructor”之类的字符串作为其键之一。它还将迭代对的扩展Object.prototype。不过,通常情况下,较短的代码看上去比较大,更健壮的代码更具吸引力,但是,答案的关键是使用ECMAScript 5th Object.keys(),它可以在不支持使用此代码的浏览器中实现。本机版本将比这具有更高的性能。
Andy E 2010年

2
非常好,Andy :)我想提醒一下-在该线程中似乎没有人提及-ES5 Object.keys仅返回与对象的可枚举属性相对应的字符串数组。在使用本机(用户定义的)对象时,这可能不是至关重要的,但对于宿主对象应该非常明显(尽管未指定的宿主对象的行为是一个单独的痛苦的故事)。要列举对所有(包括不可枚举)特性,ES5提供Object.getOwnPropertyNames(见它在我的COMPAT表支持- kangax.github.com/es5-compat-table
kangax


2
有人可以解释为什么这是这样实现的Object.keys(stuff),而不是stuff.keys()
Blazemonger's

32

请注意,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/


此外,在控制台为Chrome开发者工具,萤火虫等退房键()
萨姆·达顿


28

Object.getOwnPropertyNames(obj)

除了所显示的属性外,此功能还显示了不可枚举的属性Object.keys(obj)

在JS中,每个属性都有一些属性,包括boolean 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.getOwnPropertyNames并且Object.keys 上去原型链找到base
  • for in 确实

有关原型链的更多信息,请访问:https : //stackoverflow.com/a/23877420/895245


16

1
+1是因为我来这里的目的是构建类似的东西(尽管效果不佳)。
卡米洛·马丁

1
netgrow.com.au/assets/files/dump/dump.zip没有找到 如何下载转储的JavaScript?
Kiquenet

@Kiquenet每次我想要构建这样的东西时,我都会去找常规的对象检查器,如果您想要以HTML呈现的东西,则有npm modules之类的东西。坦白说,让我陷入困境的是我想要的东西比该图像上的要好,但从未设法将其概念化。在检查器中浏览对象虽然很糟糕,但是尝试从任意对象中推断出含义的启发式方法(例如,将对象的数组分类为带有列的表)在实践中并不总是有效的。
卡米洛·马丁

什么是Pretty Print Javascript https://j11y.io/demos/prettyprint/
Kiquenet '17

13

可以使用jQuery进行如下操作:

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

9

如果您只想获取元素而不是函数,那么此代码可以为您提供帮助

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 myJSONObject =  {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"}; 
var keys=[];
for (var i in myJSONObject ) { keys.push(i); }
alert(keys);

2
您的答案似乎与已经发布的答案相似,还有其他补充吗?
VKen 2012年


7

Mozilla提供了有关如何在不受支持的浏览器中执行此操作的完整实施详细信息,如果有帮助的话:

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的,已经给出了答案。
outis 2016年

5

采用 Reflect.ownKeys()

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

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

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


4

由于我几乎在每个项目中都使用underscore.js,因此我将使用以下keys函数:

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

的输出将是:

['name', 'hello']

这是一个常用的javascript功能的工具集库:underscorejs.org
schmijos

4

以公认的答案为基础。

如果对象具有要调用的属性,请说.properties()尝试!

var keys = Object.keys(myJSONObject);

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

0

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

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;
};
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.