Reputation: 2681
I often use for loop to iterate JavaScript objects, and have never find a problem until today. It astonished me when I am trying to know what properties an Error object have.
var e= new Error("testing");
for(var key in e)
console.log(e[key]);
I got nothing, not ouput. But of course, the following code
console.log(e.name);
console.log(e.message);
gives intended output:
"Error"
"testing"
I am not sure what is happening. I tried to Google around but have not find an answer yet. Can some one give me an explanation?
Upvotes: 7
Views: 1568
Reputation: 88
From MDN: A for...in loop only iterates over enumerable, non-Symbol properties. Objects created from built–in constructors like Array and Object have inherited non–enumerable properties from Object.prototype and String.prototype.
Upvotes: 0
Reputation: 1074148
JavaScript properties can be enumerable or non-enumerable. Non-enumerable properties are left out of for-in
loops and most other ways of getting the property names from the object.
You can get an object's own property names, including non-enumerable ones, via Object.getOwnPropertyNames
. So for instance:
Object.getOwnPropertyNames(e).forEach(function(name) {
console.log(e[name]);
});
or with ES2015+:
for (const name of Object.getOwnPropertyNames(e)) {
console.log(e[name]);
}
Note that the "own" means that it doesn't include inherited properties, which message
may or may not be depending on what JavaScript engine the code is running on. To get all of the object's string-named properties (ignoring Symbol-named ones), you need a loop looking at the prototype. You probably want to stop when you reach Object.prototype
. So:
var obj = e;
while (obj !== Object.prototype) {
Object.getOwnPropertyNames(obj).forEach(name => console.log(obj[name]));
obj = Object.getPrototypeOf(obj);
}
Upvotes: 14