Printing all the hidden properties of an object
What you're after is the non-enumerable properties of an object (and possibly those it inherits from its prototype). I don't believe there's any standard way to get them via JavaScript.
If you use a debugger and inspect an object, usually all properties of an object are shown (not just the enumerable ones). All major browsers have built-in debuggers now: Chrome has Dev Tools (Ctrl+Shift+I); IE8 and up have "F12 Developer Tools"; IE7 and earlier can be debugged via the free version of VS.Net; recent versions of Firefox have tools built in, for older versions you can get the Firebug plug-in; Opera has Dragonfly.
Update: In the comments on the question you've said:
I'm using Google Chrome 17 and the only property I see using
console.log
is__proto__
.
Right. {}
has no properties at all, just a prototype. If you click the little arrow to the left of __proto__
, it will show you __proto__
's properties. hasOwnProperty
, toString
, etc., are all properties {}
gets from the prototype (which is Object.prototype
), not properties of the object itself.
JavaScript uses prototypical inheritance, which means an object is backed by a prototype. If you try to retrieve the value of a property the object doesn't have, the JavaScript engine will look at the object's prototype to see if the prototype has that property; if so, that value is used. If the prototype doesn't have it, the engine looks at the prototype's prototype; and so on until it reaches the root of the hierarchy. This is why you hear about objects having their own properties vs. properties they inherit.
Here's an example:
Here's a constructor function. We put a property on the prototype the JavaScript engine will assign if we use new Foo
to create an object.
function Foo() {
}
Foo.prototype.bar = 42;
Let's create an object using that constructor:
var f = new Foo();
f
has no properties at all, and yet:
console.log(f.bar); // 42
...because since f
doesn't have a property called "bar", the engine looks on f
's prototype, which is the Foo.prototype
object.
Now let's give f
its own "bar" property:
f.bar = 67;
console.log(f.bar); // 67
Now let's remove f
's "bar" property:
delete f.bar;
What will happen if we try to retrieve f.bar
now?
console.log(f.bar);
If you said 42
, you get top marks. Because f
no longer has a property called "bar", we go back to getting it from the prototype.
Note that this relationship is live, so:
Foo.prototype.bar = 96;
console.log(f.bar); // 96
In the 3rd edition of ECMAScript (most browsers implement something along the lines of the 3rd edition), the only way to assign a prototype to an object is via a constructor function's prototype
property, as above. With the 5th edition, a more direct way was added: Object.create
, which you can pass a prototype object to directly:
var proto = {bar: 42};
var obj = Object.create(proto);
console.log(obj.bar); // 42
proto.bar = 67;
console.log(obj.bar); // 67
Object.getOwnPropertyNames(obj)
This will also show every non-enumerable property, although it will not follow the prototype chain lookup as .
does.
I don't know any method that both goes up the prototype chain and shows non-enumerables.
Example:
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))
// [ 'not' ]
for (var x in o)
console.log(x)
// yes, base
So we conclude:
Object.keys()
does not go up the chain, and does not show non-enumerablesfor in
goes up the chain but does not show non-enumerables
You could of course manually climb the prototype chain and use Object.getOwnPropertyNames
.
For the case of Object
, __defineGetter__
and hasOwnProperty
are properties of Object.prototype
found on new Object
objects through prototype chain lookup. So you could get them with:
console.log(Object.getOwnPropertyNames(Object.prototype))
Output:
[ 'constructor',
'toString',
'toLocaleString',
'valueOf',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'__defineGetter__',
'__lookupGetter__',
'__defineSetter__',
'__lookupSetter__' ]