As Sam Dutton answered, a new method for this very purpose has been introduced in ECMAScript 5th Edition. Object.keys()
will do what you want and is supported in Firefox 4, Chrome 6, Safari 5 and IE 9.
You can also very easily implement the method in browsers that don't support it. However, some of the implementations out there aren't fully compatible with Internet Explorer. I've detailed this on my blog and produced a more compatible solution:
(function () {
var hasOwnProperty = Object.prototype.hasOwnProperty,
hasDontEnumBug = true,
DontEnums = [
'toString', 'toLocaleString', 'valueOf', 'hasOwnProperty',
'isPrototypeOf', 'propertyIsEnumerable', 'constructor'
],
DontEnumsLength = DontEnums.length;
for (var k in {toString:null})
hasDontEnumBug = false;
Object.keys = Object.keys || 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;
};
})();
Note that the currently accepted answer doesn't include a check for hasOwnProperty() and will return properties that are inherited through the prototype chain. It also doesn't account for the famous DontEnum bug in Internet Explorer where non-enumerable properties on the prototype chain cause locally declared properties with the same name to inherit their DontEnum attribute.
Implementing Object.keys() will give you a more robust solution.
EDIT: following a recent discussion with kangax, a well-known contributor to Prototype, I implemented the workaround for the DontEnum bug based on code for his Object.forIn()
function found here.