how to write for-each loop in JavaScript properly

3,880 views
Skip to first unread message

Shimon Doodkin

unread,
Feb 12, 2012, 7:42:51 AM2/12/12
to nodejs
for (var key in myobj) must be accompanied with
if(Object.hasOwnProperty.call(myobj,key))

example:

for (var key in myobject) {
if(Object.hasOwnProperty.call(myobject,key)){
...
}
}

myobject.forEach(function(){...}) already does this.


more:

You could do : myobj.hasOwnProperty(key) But then if myobj is NULL it
will throw an error.
So you use the method hasOwnProperty from the prototype object.
and you call it with changing the this object of it to your object.

Object.hasOwnProperty.call(myobj,key)

Most of you probably know this, but sometimes I encounter modules that
don't do this.
And they do unexpected errors.

bradley griffiths

unread,
Feb 12, 2012, 8:50:54 AM2/12/12
to nod...@googlegroups.com
I normally do:

Object.keys(myobject).forEach(function(key){
  myobject[key];
});

Is this a bad way to do it?

Joe Developer

unread,
Feb 12, 2012, 9:40:11 AM2/12/12
to nod...@googlegroups.com
Requests for enlightenment:

On Sun, Feb 12, 2012 at 7:42 PM, Shimon Doodkin <helpm...@gmail.com> wrote:
for (var key in myobj) must be accompanied with
if(Object.hasOwnProperty.call(myobj,key))

example:

for (var key in myobject) {
     if(Object.hasOwnProperty.call(myobject,key)){
        ...
     }
   }

myobject.forEach(function(){...}) already does this.


more:

You could do :  myobj.hasOwnProperty(key) But then if myobj is NULL it
will throw an error.

Wouldn't it be more efficient to simply check if myobj is null before trying to iterate over it?
In similar vein,  wouldn't it be better to not declare the var inside the for() in this instance?

I realize that for the vast majority of cases the contents of the loop will be far heavier than the scaffolding involved, but since we are presenting 'best practice' scenarios for something that I would imagine would often sit in a util function somewhere...

I have created: http://jsperf.com/obj-property-iteration in case it might have value, if nothing else to have a place to tack on various approaches.


So you use the method hasOwnProperty from the prototype object.
and you call it with changing the this object of it to your object.

Object.hasOwnProperty.call(myobj,key)

Most of you probably know this, but sometimes I encounter modules that
don't do this.
And they do unexpected errors.

--
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 nod...@googlegroups.com
To unsubscribe from this group, send email to
nodejs+un...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en

Joe Developer

unread,
Feb 12, 2012, 9:42:20 AM2/12/12
to nod...@googlegroups.com
In environments that support it, it seems like one of the very fastest approaches.
What is interesting, from my superficial test runs at  http://jsperf.com/obj-property-iteration is that Chrome, atleast, seems able to optimize the work-payload quite impressively.

Diogo Resende

unread,
Feb 12, 2012, 2:07:28 PM2/12/12
to nod...@googlegroups.com
On Sun, 12 Feb 2012 04:42:51 -0800 (PST), Shimon Doodkin wrote:
> You could do : myobj.hasOwnProperty(key) But then if myobj is NULL
> it
> will throw an error.

It will probably throw 1 or 2 lines before in the "for (...)".

If you're using an object as a hash you can avoid it. If you want to be
sure, I use this:

for (k in obj) {
if (!obj.hasOwnProperty(k)) continue;
..
}

Or if I can, I don't need to handle "this" references, I use .forEach.

---
Diogo R.

Marcel Laverdet

unread,
Feb 12, 2012, 3:09:55 PM2/12/12
to nod...@googlegroups.com
This is one of those old Crockfordisms that I definitely don't agree with. How about instead you just don't add garbage to Object.prototype? Or if you do make them DontEnum. Do you really write two-line loop headers every time you want a loop??

Andy

unread,
Feb 12, 2012, 3:57:50 PM2/12/12
to nod...@googlegroups.com

Most of you probably know this, but sometimes I encounter modules that
don't do this.
And they do unexpected errors.

Now that you've discovered Crockford, you should discover when to ignore crockford

Kilian C.

unread,
Feb 12, 2012, 6:19:12 PM2/12/12
to nod...@googlegroups.com
On Sun, Feb 12, 2012 at 3:40 PM, Joe Developer <joe.d.d...@gmail.com> wrote:
Requests for enlightenment:

On Sun, Feb 12, 2012 at 7:42 PM, Shimon Doodkin <helpm...@gmail.com> wrote:
for (var key in myobj) must be accompanied with
if(Object.hasOwnProperty.call(myobj,key))

example:

for (var key in myobject) {
     if(Object.hasOwnProperty.call(myobject,key)){
        ...
     }
   }

myobject.forEach(function(){...}) already does this.


more:

You could do :  myobj.hasOwnProperty(key) But then if myobj is NULL it
will throw an error.

Wouldn't it be more efficient to simply check if myobj is null before trying to iterate over it? 
In similar vein,  wouldn't it be better to not declare the var inside the for() in this instance?

 Doesn't matter where you declare a variable, V8 will move you declaration to the top of the current scope.

Martin Cooper

unread,
Feb 13, 2012, 12:14:23 AM2/13/12
to nod...@googlegroups.com
On Sun, Feb 12, 2012 at 12:09 PM, Marcel Laverdet <mar...@laverdet.com> wrote:
> This is one of those old Crockfordisms that I definitely don't agree with.
> How about instead you just don't add garbage to Object.prototype?

Depends on how much control you have over all the code in your
environment. Things are somewhat better in Node land, but in browser
land, all it takes is some library you're using that augments
Object.prototype and you're hosed unless you protect your own
enumerations from such augmentation.

--
Martin Cooper

Brandon Benvie

unread,
Feb 13, 2012, 1:58:26 AM2/13/12
to nod...@googlegroups.com
Technically that's how javascript works everywhere. All declarations are hoisted to the top of the current scope. ES6 introduces block scoping which Node (V8) supports when using `node --harmony`. This introduces `let` which will replace `var` and is block scoped instead of function scoped. Prior to ES6 javascript has only function scoping.

Marcel Laverdet

unread,
Feb 13, 2012, 2:31:59 AM2/13/12
to nod...@googlegroups.com
No one augments Object.prototype in the browser because if you do everything dies. "Don't use Object.prototype" is a much better rule than "write ridiculous guards on every loop". Libraries don't just sneak into your project you have to put them there and it will be very apparent if you ever run across one that touches O.proto. And it also won't be a very popular library. And it will also be easy to fix.

Thom Blake

unread,
Feb 13, 2012, 9:43:58 AM2/13/12
to nodejs
> Or if you do make them DontEnum.

DontEnum is not a property that can be set by the user.

On Feb 12, 3:09 pm, Marcel Laverdet <mar...@laverdet.com> wrote:
> This is one of those old Crockfordisms that I definitely don't agree with.
> How about instead you just don't add garbage to Object.prototype? Or if you
> do make them DontEnum. Do you really write two-line loop headers every time
> you want a loop??
>

Thom Blake

unread,
Feb 13, 2012, 9:46:01 AM2/13/12
to nodejs
Well, in < ES4 that is.

Axel Kittenberger

unread,
Feb 13, 2012, 10:01:43 AM2/13/12
to nod...@googlegroups.com
> You could do :  myobj.hasOwnProperty(key) But then if myobj is NULL it will throw an error.

Unless nil suddendly has keys, it wouldn't go into loop anyway.

Personally I don't like forEach too much, since I cannot break from
it, when I decide the rest is uninteresting. Or even return from the
parents function. At least not without some
oh-so-clever-but-ugly-misuse of exceptions. Why they didn't make the
standard forEach in that returning false terminates the loop is beyond
me, or even designed javascript so you can do "named returns", that is
returning directly the closures parent, which only would work if the
closure is not exported out of the function anyway. But honestly this
is all off-topic to Node.js. To Node javascript comes with its quirks
as it is, and is no language design project.

substack

unread,
Feb 13, 2012, 11:47:42 AM2/13/12
to nodejs
On Feb 13, 7:01 am, Axel Kittenberger <axk...@gmail.com> wrote:
> Why they didn't make the standard forEach in that returning false
> terminates the loop is beyond me...

You can just abuse the short-circuiting of [].some:

> [ 1, 2, 3, 4, 5, 6, 7 ].some(function (x) { console.log(x); if (x > 4) return true })
1
2
3
4
5

Instead of `return false`, it's `return true`.

Tim Caswell

unread,
Feb 13, 2012, 11:47:41 AM2/13/12
to nod...@googlegroups.com
Since this is the nodejs list, I'm going to assume you're working in
node. In that case, Object.keys is built-in and it's really fast in
V8 (much faster than for .. in). Also if you want to share code with
the browser and it's not a mobile app (meaning it needs to support old
ES3 browsers), then it's easy and safe to add an Object.keys function.
It's not on the object prototype.

function forEach(obj, callback, thisp) {
var keys = Object.keys(obj);
for (var i = 0, l = keys.length; i < l; i++) {
var key = keys[i];
if (callback.call(thisp, obj[key], key, obj) break;
}
}

Then to use this function, simply do:

forEach(obj, function (value, key) {
// do something
});

If you want to preserve your "this" value, just pass it in as an
argument after the callback. The built-in Array.prototype.forEach
works just like this. If you're comfortable changing
Object.prototype, then put this function there (moving the first
argument to `this`).

If you want to be able to break out of the loop, simply return true
from the callback.

For older browsers, Object.keys can be implemented simply as:

Object.keys = function (obj) {
var key, keys = [];
for (key in obj) {
if (!obj.hasOwnProperty) continue;
keys.push(key);
}
return keys;
};

Axel Kittenberger

unread,
Feb 13, 2012, 12:21:42 PM2/13/12
to nod...@googlegroups.com
some() is only for Arrays tough.

Tim Caswell

unread,
Feb 13, 2012, 1:11:21 PM2/13/12
to nod...@googlegroups.com
On Mon, Feb 13, 2012 at 11:21 AM, Axel Kittenberger <axk...@gmail.com> wrote:
> some() is only for Arrays tough.

Same with forEach. I had forgotten about Array.prototype.some().

If you want the short-circuit of some, use my code from above, but
call it "some" to avoid confusion.

Shimon Doodkin

unread,
Feb 13, 2012, 1:31:19 PM2/13/12
to nodejs
My post mainly about loops, not about prototypes. To not use
prototypes when you write a plugin script to be integrated into 3rd
parity website is a very good idea.

Generaly Node.js is very controlled-settings environment.
I like to add some agile convenience by using prototypes,
I add them to to Strings and sometimes to Objects, to modernize
JavaScript a little bit.
For me, it's worth it.

-------

Bradley Griffiths, Joe Developer:
Awesome

about Tim Caswell's message about missing Object.keys:

The better compatibility implementations are found at Mozilla
Developer Network website
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys

Marcel Laverdet:
Humm, interesting, I see what you mean:

Object.prototype.defineProperty(obj, "newDataProperty", {
value: function(){},
writable: false,
enumerable: false,
configurable: true
});// from: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/defineProperty


Thanks, real value to the conversation

However I am concerned about: Maybe a loop should not iterate on
prototype's properties.



Thanks Everybody.


On Feb 12, 4:40 pm, Joe Developer <joe.d.develo...@gmail.com> wrote:
> Requests for enlightenment:
>
> On Sun, Feb 12, 2012 at 7:42 PM, Shimon Doodkin <helpmep...@gmail.com>wrote:
>
>
>
>
>
>
>
>
>
> > for (var key in myobj) must be accompanied with
> > if(Object.hasOwnProperty.call(myobj,key))
>
> > example:
>
> > for (var key in myobject) {
> >      if(Object.hasOwnProperty.call(myobject,key)){
> >         ...
> >      }
> >    }
>
> > myobject.forEach(function(){...}) already does this.
>
> > more:
>
> > You could do :  myobj.hasOwnProperty(key) But then if myobj is NULL it
> > will throw an error.
>
> Wouldn't it be more efficient to simply check if myobj is null before
> trying to iterate over it?
> In similar vein,  wouldn't it be better to not declare the var inside the
> for() in this instance?
>
> I realize that for the vast majority of cases the contents of the loop will
> be far heavier than the scaffolding involved, but since we are presenting
> 'best practice' scenarios for something that I would imagine would often
> sit in a util function somewhere...
>
> I have created:http://jsperf.com/obj-property-iterationin case it might

Axel Kittenberger

unread,
Feb 13, 2012, 1:38:32 PM2/13/12
to nod...@googlegroups.com
I still dislike forEach() same as some(); since the semantics are just
more complicated. break doesn work (ok return true), but named break
is gone, continue is now called return, and named continue is gone,
and you cannot return from the parent function, which often I do to
shortcut. You lose so much and gain so little. this pointer is not
the objects method you are in, but the array/object, etc. I'm with
Marcel most of my objects just don't come with non-owned clutter,
for(key in obj) just keeps the semantics better and will do fine, and
if they do,
if (!obj.hasOwnProperty(key)) continue;
isn't that hard. And before I use that forEach() and a callback id
just write this if performance is a consideration:
for (var i = 0, iK = Object.keys(obj), iZ = iK.length; i < iZ; i++) {
Its still a one-liner (ok two if you need to get key/val), and once
you get used to it, it just like a phrase hardly using brain-cells to
go through

But in the end its just taste/style and there is not "right" answer.

Jimb Esser

unread,
Feb 14, 2012, 3:25:09 AM2/14/12
to nodejs
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. Object.keys seems to
often be very fast compared to calling Object.hasOwnProperty on each
element inside of a for..in, but it seems to have a lot of overhead
and be much slower than for..in on small objects.

Some jsperf entries and my perf difference in Chrome:
http://jsperf.com/object-keys-vs-for-in-for-values/8 (Object.keys 70%
slower just getting an array of keys on small objects)
http://jsperf.com/object-keys-vs-for-in-for-values/7 (Object.keys 80%
slower iterating over values on small objects)
http://jsperf.com/obj-property-iteration/3 (test earlier in the
thread; for..in 20% slower on larger (100 member) object)

These are all pretty contrived test cases, and running the same small
code over and over again in a perf test seems to not necessarily
translate well to an actual app running lots of different small bits
of code at random (at least as far as V8's optimizer is concerned -
perhaps it unrolls the small loops in the first test?), so I'm not
completely confident from just those tests.

At least in Chrome, we've seen very bad garbage collection hitches in
V8, and using either closures or even a function made with
Function.prototype.bind adds a lot of extra pressure to the heap,
greatly increasing the frequency and/or cost of garbage collection
stalls. We're working on a 3D WebGL engine, and the garbage
collection stalls are very noticeable if they're happening with any
frequency. Anyway, a bunch of random anecdotal evidence, but after
converting all of our code to use for..in instead of closures passed
to iterator functions, we saw much improved performance (primarily
from untolerable 500ms garbage collect stalls every 10s or so down to
acceptable <50ms garbage collect stalls at around the same frequency).

It seems, at least currently for our project, if we're working with
small data sets, in trusted code, for..in with no guards is the best
performing (as well as arguably the simplest to read).

If you're writing modules though, please always use Object.keys or a
loop guarded with .hasOwnProperty to be safe, it really sucks when an
external module breaks for no clear reason.

Once we added a once-per-frame "for (var i in {}) throw 'some idiot
extended Object.prototype';", we've been able to be much more
confident in ensuring our for..in code is (relatively) safe.

jimb

Scott González

unread,
Feb 14, 2012, 6:44:24 AM2/14/12
to nod...@googlegroups.com
On Tue, Feb 14, 2012 at 3:25 AM, Jimb Esser <wast...@gmail.com> 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.

Tim Caswell

unread,
Feb 14, 2012, 10:38:02 AM2/14/12
to nod...@googlegroups.com
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 <scott.g...@gmail.com>:

Axel Kittenberger

unread,
Feb 14, 2012, 12:32:24 PM2/14/12
to nod...@googlegroups.com
I think this is a good example for, that haziness of performance
optimization in a script language like JS. What may be efficient to
the engine today, might not so be in future and vice verca. We'll just
have to live with it.

I remember the older days of JS, where JS-engines were so slow,
anything you could possible offload to native code was a gazillion
times faster, even if it would be ridiculously more complicated done
there. I used to write some calculations by changing them to string
and doing some crazy regexps, since regexp engine was way faster than
JS. Or I daresay the most efficient way for deep cloning was
JSON.parse(JSON.stringify(obj)); Likely, not so today. Or before the
V8 came around with its hidden classes, some design decissions where
more taste than performance to cater for them.

Overall, albeit I'd like to have a good link for V8 optimizations,
tons of micro-optimizations hardly make you happy nor improve your app
significantly, most profiles I ran on projects on mine, the first
result was quite a surprise to me where 80% of the time is actually
burned.

Reply all
Reply to author
Forward
0 new messages