Also note that performance changes over time. Last time I benchmarked
for..in vs Object.keys was many V8 versions ago. They may have
optimized for..in more since then.
One very important thing to remember in benchmarks, especially
micro-benchmarks like this is that your loop is probably not your
bottleneck. It's good to be performance aware and responsible with
resources, but it's not the only design constraint in your program.
It can be in some cases, but not usually.
What probably matters a lot more is the different semantics. As Scott
explained so clearly, the two works differently. If I don't want
deleted keys to go away during my loop, I'll save a snapshot of the
old keys using Object.keys and loop over that. If I want a scope per
loop iteration I'll use forEach. Local variables are very handy for
closures, remember that normal for loops don't have their own scope
and share with the surrounding code. If you have a callback in your
loop that uses a variable from the loop body, you most likely want to
use forEach or something that creates a new scope for the loop
iteration. If you want to use block semantics and like `continue` and
`break` (which support named goto btw) then use normal for(;;) or
for..in loops.
If you want a snapshot of the keys before the loop, use Object.keys.
If you want to include properties in the prototype chain or want
deleted keys to not get iterated over, then use for..in.
A separate concern is if you want a scope per iteration. Both for..in
and Object.keys can be used with either loop method:
// for..in with block semantics
for (key in obj) {
if (!obj.hasOwnProperty(key)) continue; // optional if you don't
want to include enumerable prototype properties
// do something, break. or continue
}
// for..in with scope per iteration
for (key in obj) {
loop(key)
}
function loop(key) {
setTimeout(function () {
// `key` is still the key from this iteration!
}, 100);
}
// Object keys with block semantics
var keys = Object.keys(obj);
for (var i = 0, l = keys.length; i < l; i++) {
var key = keys[i];
// do something with key, continue or break
}
// Object.keys with scope per loop
Object.keys(obj).forEach(function (key) {
setTimeout(function () {
// key is the one from this iteration, not the last key
}, 100)
});
These aren't the best ways to implement these various loops, they
merely show that with a good understanding of the language about any
kind of loop can be figured out.
In node I find it very useful to have a scope per iteration since I
often make async calls in my loop (parallel work ftw!) and with block
level loops the iteration variable changes to the last item in the
loop before the callback ever fires leading to nasty bugs.
But sometimes I'm writing a synchronous parser or compiler and block
tools are much more useful in that case (switches inside switches
inside for(;;) with continue and break all over the place)
Sorry for derailing the list with performance implications that seems
to have changed a little in the last year.
Happy coding everyone!
-Tim Caswell
2012/2/14 Scott González <[email protected]>:
> On Tue, Feb 14, 2012 at 3:25 AM, Jimb Esser <[email protected]> wrote:
>>
>> I keep reading things saying "Object.keys is much faster than
>> for..in", but in most tests I do (and in a bunch I find on
>> jsperf.com), that is the opposite of the case.
>
>
> There are two big differences:
>
> 1) for..in walks the prototype chain, while Object.keys() does not.
> 2) for..in is dynamic in that it detects keys that are deleted during the
> loop.
>
> For objects with very few properties and very shallow prototype chains,
> for..in may be faster. As the number of properties and/or the depth of the
> prototype chain grows, Object.keys() will get faster.
>
> --
> Job Board: http://jobs.nodejs.org/
> Posting guidelines:
> https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
> You received this message because you are subscribed to the Google
> Groups "nodejs" group.
> To post to this group, send email to [email protected]
> To unsubscribe from this group, send email to
> [email protected]
> For more options, visit this group at
> http://groups.google.com/group/nodejs?hl=en?hl=en
--
Job Board: http://jobs.nodejs.org/
Posting guidelines:
https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en