1

To be IE compatible we decided to use classic for loop for arrays:

for (var i = 0; i < arr.length; ++i) { ... }

and adding obj.hasOwnProperty(key) for object for loops:

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

But... Is this really required?

I remember that I looked in the jQuery source code and I didn't find this condition when iterating objects.

Also, if the answer is yes, is there any shorter solution than adding if(!obj.hasOwnProperty(key)) continue; to every object iterating? I mean to rewrite for somehow...

To be clear: if instead of for (var k in o) { ... } I would use:

foo (o, function (k) {
   ...    
});

function foo (o, callback) {
    for (var k in o) {
        callback (k);
    }
}

I would just add the if only one time, in foo function. But consider having a lot of object for loops. Is there any solution to rewrite for?

Ionică Bizău
  • 109,027
  • 88
  • 289
  • 474
  • @Teemu Why isn't it required? Why will it fail? – Ionică Bizău Dec 21 '13 at 20:02
  • @Teemu I use regular for lop for arrays, but for objects I think that `in` is required. (see how my question starts) – Ionică Bizău Dec 21 '13 at 20:06
  • If you're only iterating objects that you yourself created, and you don't add anything to the prototype of Object, the object shouldn't contain any values that would cause issues, and then there's no need to check if the the objects hasOwnProperty. – adeneo Dec 21 '13 at 20:06
  • 1
    that's why i like Object.keys(obj).forEach()... – dandavis Dec 21 '13 at 20:11
  • @dandavis Now, it's too late. I would like to add few lines in a script and to make all for blocks that don't use `if(!obj.hasOwnProperty(key)) continue;` compatible with IE. – Ionică Bizău Dec 21 '13 at 20:14
  • 2
    @イオニカビザウ note that this has **nothing** to do with Internet Explorer. The `.hasOwnProperty()` check is a good idea in **all** browsers (if you're not using `Object.keys()`). – Pointy Dec 21 '13 at 20:21

2 Answers2

3

You can try this:

  function foo(o, callback) {
    var i, k = Object.keys( o );
    for (i = 0; i < k.length; ++i)
      callback(o[k[i]], k[i]);
  }

Note that you probably should be passing the value at each key to the callback, and not just the key. If you just want to iterate through an object without a helper function, then, it's:

var keys = Object.keys( obj ), value;
for (var i = 0; i < keys.length; ++i) {
  value = obj[ keys[ i ] ];
  // ...
}

Object.keys() returns an array, so you can use array-style iteration with an index.

The Object.keys() function doesn't exist in older browsers, but you can use a pollyfill like the one at the MDN site. The function does not return inherited properties, so no .hasOwnProperty() test is needed.

If you're 100% sure that your code is never going to run in a context where other code has modified the prototype objects of various built-in (and, for that matter, non-builtin) constructors, then you don't need to worry about .hasOwnProperty(). However, since the bugs that such problems introduce are usually pretty serious and weird, it's probably worth checking.

edit — fancier version:

function foo(o, callback) {
  Object.keys(o).forEach(function(k) { callback( o[k], k ); });
}
Pointy
  • 405,095
  • 59
  • 585
  • 614
  • I don't have a `foo` function. I have a looot of for loops that iterate objects. `if(!obj.hasOwnProperty(key) continue;` works fine, but the question is if is there any shorter solution? – Ionică Bizău Dec 21 '13 at 20:04
  • @イオニカビザウ well I just used that for the example. The point is that with `Object.keys()` you don't have to call `.hasOwnProperty()` because it already effectively does that check for you.. – Pointy Dec 21 '13 at 20:07
  • That's true, but still this doesn't answer to the second part of the question: *how can we rewrite for?* I don't have a function like `foo`, so that means to edit each for block... – Ionică Bizău Dec 21 '13 at 20:10
  • @イオニカビザウ I thought it was clear, but I'll add more to the answer. – Pointy Dec 21 '13 at 20:18
  • I think I am not clear enough... :-) Imagine that I have to edit 3000 for loops. I would like to add few lines in a js file and to make all 3000 for loops IE compatible without edit them. Is this possible? – Ionică Bizău Dec 21 '13 at 20:22
  • @イオニカビザウ No, that is not possible. That's why it's actually a good idea to write code with things like you're fictional "foo" function instead :) The `in` operator works the way it works, in other words, and you cannot change that. – Pointy Dec 21 '13 at 20:24
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/43676/discussion-between---and-pointy) – Ionică Bizău Dec 21 '13 at 20:26
2

It's not required.

Just make sure to code array loops correctly and not to vandalize prototypes. Attention is only required when you have horribly coded third-party modules which you cannot omit.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375