Javascript has a great convenience method for iterating through objects or arrays, called
for(item in container)
Which should be familiar to developers acquainted with Python/Ruby/C++/many other languages, which have similar concepts of iterables.
var obj = {
a: 1,
b: 2,
};
undefined
for (item in obj) {
console.log("obj has key %s", item);
}
obj has key a obj has key b
undefined
But JavaScript always has a way to ruin your day:
Object.prototype.wtf = 'wtf';
for (item in obj) {
console.log("obj has key %s", item);
}
obj has key a obj has key b obj has key wtf
undefined
So for-in
is never safe. There is a helpful Object.keys()
function (don't ask me why it's not a method):
Object.keys(obj);
[ 'a', 'b' ]
So let's give it a try, shall we?
for (var key in Object.keys(obj)) {
console.log("Object.keys(obj) has key", key);
}
Object.keys(obj) has key 0 Object.keys(obj) has key 1 Object.keys(obj) has key wtf
undefined
WTF, indeed! for-in
arrays iterates through indices for some reason instead of elements, plus since arrays are objects, for-in
is also ruined.
You can use Array.map
with Object.keys
, if it's okay to call a function on every iteration:
Object.keys(obj).map(function (key) {
console.log("obj[%s] = %s", key, obj[key]);
});
obj[a] = 1 obj[b] = 2
[ undefined, undefined ]
Or you can resort to the super-awesome Object.hasOwnProperty filter on the original for-in:
for(var key in obj) {
if (!obj.hasOwnProperty(key)) continue;
console.log("obj[%s] = %s", key, obj[key]);
}
obj[a] = 1 obj[b] = 2
undefined
There's allegedly hope in the form of for-of, which aims to do what for-in
always should have done,
but that is dashed by it apparently being crazy slow.