如何列出JavaScript对象的属性?

970

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

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

如何最好地检索属性名称列表?也就是说,我想最终得到一些变量'keys',使其具有以下特点:

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

3
有一点跑题,但如果你使用underscore.js:_.keys(myJSONObject) - Endy Tjahjono
5
如果您仅想获取可枚举的属性,请使用 Object.keys(obj)。但有时您也需要获取不可枚举的属性。如果需要获取这些属性,请记住使用 Object.getOwnPropertyNames(obj)。参考来源:https://dev59.com/9nVC5IYBdhLWcg3wsTfv#32413145 - Andrew
18个回答

1218

在现代浏览器(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()。扩展原型会带来一些副作用,我不建议这样做。


19
我会进行更新,以达到“你可能会想要对对象原型执行此操作......但不要这样做!”的效果。 - AnthonyWJones
5
为什么不建议向Object原型添加函数?有人能否说明一下原因? - Vishwanath
2
这是一个完全不同的问题,快速在StackOverflow或Google上搜索将会给你大量阅读材料。 - ximi
4
for (var key in myObject) {...} 技术在浏览器和 V8 之外的 JavaScript 运行时非常有用。例如,在将 JavaScript map-reduce 查询传递到 Riak 时,由于 Object 对象不存在,因此 Object.keys 方法不可用。 - awhie29urh2
24
@slashnick,你的“简化版本”返回对象原型链中的所有属性(因为它使用了“for ... in”),而(ECMAScript 5.1)Object.keys方法仅返回对象自身的属性。我认为这是一个重要的区别。 - Martin Carel
显示剩余4条评论

271

正如slashnick所指出的,你可以使用"for in"结构来迭代对象的属性名。但是,你将遍历对象原型链中所有的属性名。如果你只想迭代对象自己的属性,你可以使用Object#hasOwnProperty()方法。因此,可以得到以下内容。

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

30
我希望在slashnic上面的回答之前读过这个。我刚刚不得不花费15分钟按住“esc”键,因为该对象有大约一百万个属性,其中大多数都没有使用,并且我对其进行了警报。 - Mark Henderson
4
LOL @MarkHenderson - 但下次直接结束浏览器进程并重新启动,而不要浪费15分钟 :) - JD Smith
一个相关的函数是obj.getOwnPropertyNames() - https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames - Steve Goodman
@MarkHenderson 为什么你不使用 console.log? - LasagnaAndroid
很好,应该更新已选择的答案,而不是添加一个新的。 - LasagnaAndroid

105
作为Sam Dutton的回答,ECMAScript第五版引入了一种新的方法来实现这个目的。 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()将为您提供更强大的解决方案。
编辑:根据与kangax的最近讨论,Prototype的知名贡献者,我基于他发现的Object.forIn()函数的代码实现了DontEnum bug的解决方法,该代码可以在here找到。

1
@David Caunt:谢谢 :-) 不幸的是,被接受的答案仍然会遇到DontEnum bug,而且你永远不知道JSON对象可能有一个像"valueOf"或"constructor"这样的字符串作为其键之一。它还将迭代Object.prototype的扩展。虽然通常情况下,较短的代码看起来比更大、更健壮的代码更具吸引力,但这个答案的重点是使用ECMAScript 5th的Object.keys(),可以在不支持它的浏览器中使用此代码实现。本机版本甚至比这个更高效。 - Andy E
2
非常好,Andy :) 我只想提醒一下,在这个主题里似乎没有人提到——ES5 的 Object.keys 只返回一个数组,其中包含一个对象的可枚举属性所对应的字符串。当使用本机(用户定义)对象时,这可能并不重要,但当使用宿主对象时,这就应该非常明显了(尽管未指定的主机对象行为是一个独立而痛苦的故事)。为了枚举所有(包括不可枚举)属性,ES5 提供了 Object.getOwnPropertyNames(请参见我的 compat. 表中的支持- http://kangax.github.com/es5-compat-table/)。 - kangax
2
我已将此解决方案集成到es5-shim中 http://github.com/kriskowal/es5-shim/blob/master/es5-shim.js#L390 - Kris Kowal
2
有人能解释一下为什么要实现成 Object.keys(stuff) 而不是 stuff.keys() 吗? - Blazemonger
http://ww1.whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation 未找到,可能在archive.org中找到? - Kiquenet
显示剩余7条评论

43

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

例如:

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

ECMAScript 5兼容性表

新方法概述


还可以在Chrome Dev Tools、Firebug等控制台中使用keys()。 - Sam Dutton
未找到http://markcaudill.com/index.php/2009/04/javascript-new-features-ecma5/。 - Kiquenet

36

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://dev59.com/a3RB5IYBdhLWcg3wn4UL#23877420


17

1
+1 是因为我来这里的初衷是要构建类似的东西(虽然不如此好)。 - Camilo Martin
1
http://www.netgrow.com.au/assets/files/dump/dump.zip 未找到。我该如何下载 dump javascript? - Kiquenet
@Kiquenet 每次我想要构建类似的东西时,我都会满足于常规的对象检查器,如果你想在HTML中呈现它,有一些像npm模块这样的东西。坦白地说,让我困惑的是,我想要比那个图像更好的东西,但从未设想过它。在检查器中浏览对象很糟糕,但是试图从任意对象中推断出含义的启发式方法(例如,将对象数组分类为具有列的表)并不总是实用。 - Camilo Martin
1
Pretty Print Javascript是什么?_https://j11y.io/demos/prettyprint/_ - Kiquenet

15

可以使用jQuery完成如下操作:

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

10

如果你只想获取元素而不是函数,那么这段代码可以帮助你。

this.getKeys = function() {

    var keys = new Array();
    for(var key in this) {

        if( typeof this[key] !== 'function') {

            keys.push(key);
        }
    }
    return keys;
}

这是我实现HashMap的一部分,我只想要键(key),“this”是包含这些键的HashMap对象。


10

这将在大多数浏览器中工作,甚至在IE8中也可以,不需要任何库。变量i是你的键。

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

2
你的回答似乎与已发布的类似,还有其他补充吗? - VKen

9

使用 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()]

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