4

I'm making a small jQuery-like library, and one thing striking me odd is the behavior of $.each.

In javascript we have a for...in loop:

for (var key in obj) {
    console.log(key + ': ' + obj[key]);
}

The problem with this, is that it will iterate over inherited properties as well, that is, properties coming from the object constructor's prototype.

One can know this using hasOwnProperty, for example. And jQuery could do that.

But, when you pass an object to $.each, it behaves exactly like a for...in, iterating over inherited properties as well. It also should be marginally slower, and requires a few more characters to type.

Check this fiddle to see it in action and look here for the source code of $.each.

So my question is, is there an object iteration method in jQuery that only includes own properties? If not, should a library behave like this?

Edit: Since jQuery does not do this, you can also answer if this is useful. I mean, I cannot see myself wanting to iterate over prototype properties, but maybe I'm missing something.

Camilo Martin
  • 37,236
  • 20
  • 111
  • 154
  • Have a look here too http://stackoverflow.com/questions/1827458/prototyping-object-in-javascript-breaks-jquery – mplungjan Dec 03 '12 at 17:18
  • 1
    The only way to find it is by using `hasOwnProperty`. http://jsfiddle.net/mpTkA/2/ – Selvakumar Arumugam Dec 03 '12 at 17:19
  • 1
    There's also `Object.keys()` in newer browsers. – Pointy Dec 03 '12 at 17:22
  • agreed, with @Vega, afraid this is the only way, no sugar from jQuery in this prospective – dmi3y Dec 03 '12 at 17:23
  • @dmi3y Ah, I see, that's sad. I wonder if a library is supposed to behave this way, since I'm having to decide that at the moment. – Camilo Martin Dec 03 '12 at 17:24
  • @Vega I even mentioned `hasOwnProperty` in the question. – Camilo Martin Dec 03 '12 at 17:27
  • @CamiloMartin Yes I know.. that is why It was not in answers :) – Selvakumar Arumugam Dec 03 '12 at 17:28
  • 1
    @Pointy, good to know) probably the [`getOwnPropertyNames`](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames) would be even better – dmi3y Dec 03 '12 at 17:30
  • @dmi3y Not if you need to support IE8. – Camilo Martin Dec 03 '12 at 17:32
  • yep, that's why it is not the answer) just bit more information for future – dmi3y Dec 03 '12 at 17:34
  • 1
    **Quick note:** Make sure that if you use the native `for`-`in`, you use a `var` for the `key`: `for (var key in obj)`. Otherwise you'll get an accidental global. (Unless you really want `key` to be global, in which case, you should likely find a better way of doing whatever it is you want to do.) **Other quick note:** When using `hasOwnProperty`, it can be slightly safer to save a reference instead of calling it by dot-notation: `var has = Object.prototype.hasOwnProperty; has.call({abc: 'xyz'}, 'abc');`. – Keen Dec 03 '12 at 18:49
  • @Cory oh yes, you're completely right. I missed that. And I can see your second point does make sense (albeit I'm not sure who would tinker with hasOwnProperty...). – Camilo Martin Dec 03 '12 at 19:17

1 Answers1

1

The jQuery behavior makes sense, as you can always choose to add the hasOwnProperty check in the loop - or not.

I can see that looping through inherited properties could be useful in some scenarios (cloning or sub-class or whatever you call it).

Christophe
  • 27,383
  • 28
  • 97
  • 140
  • 1
    That "some scenarios" part is the one I couldn't figure out. Do you have any example? (And, if one has to add the `hasOwnProperty` check, one could as well use `for...in` and save some typing). – Camilo Martin Dec 03 '12 at 17:39
  • For example: defaultAjaxSettings={type:"GET",...}, then create a clone that has some specific settings but for the rest inherits from the default settings? – Christophe Dec 03 '12 at 17:44
  • 1
    I see... but normally one uses something like `$.extend` to deal with defaults in option maps, right? Or in some framework it is more common to do it like this, with inheritance? – Camilo Martin Dec 03 '12 at 17:53
  • right... honestly I don't know. Obviously you'd want to use inheritance when you need to propagate changes to the default settings , but I don't have a better example. – Christophe Dec 03 '12 at 18:18
  • Also, I think the interest of $.each is to provide an abstraction layer that works with various collections (objects, arrays), and this might be interesting in some scenarios like templating. But again I don't have a specific example... – Christophe Dec 03 '12 at 18:21