1

For example:

var d = [];

d[3] = 'qwe';
d[10] = '213';

console.log(d);
for(i in d){
    console.log(i);
    console.log(d[i]);
}

$.each(d, function(i, v){
    console.log(i);
    console.log(v);

});

First output: [undefined, undefined, undefined, "qwe", undefined, undefined, undefined, undefined, undefined, undefined, "213"]

for loop returns only two right values, but $.each loop returns 10 elements with 8 "undefined". I understand why it happens, but I want use exactly jQuery $.each for my script.

Thanx.

1
  • You say "first output" has the undefineds, but the first code you show is the for loop which won't have those undefineds. I assume you mean you're seeing those in the $.each loop. Commented May 1, 2011 at 8:20

5 Answers 5

4

The output you've shown doesn't match either of the loops you've shown, but the gist seems to be that you don't want to see the undefined array entries.

I understand why it happens, but I want use exactly jQuery $.each for my script.

If you really want to do that, it's easy enough:

$.each(d, function(i, v){
    if (d.hasOwnProperty(i)) {
        console.log(i);
        console.log(v);
    }
});

That will weed out the array indexes that don't exist in the array. You could use typeof v[i] !== 'undefined' but that will give you the incorrect result if you've actually set an array element to undefined (so it exists, but its value is undefined).

jQuery is iterating over the array in the normal way, starting with index 0 and going through to index length - 1. The for..in loop loops over the properties in the object, and so doesn't loop for non-existant array entries (but will, the way you've written it, pick up anything from Array.prototype that's enumerable; more here).

Ways to loop things:

  1. $.each; see above.

  2. Specifically for arrays and array-like things, the staid but useful for (index = 0; index < v.length; ++index). In this case, because the array is sparse, you'll want v.hasOwnProperty(i) or typeof v[i] !== 'undefined' (if you don't care about the case I listed above) to make sure you're seeing an entry that exists.

  3. For objects in general (including arrays, but you have to be careful): for..in:

    for (propName in v) {
        // Check whether `v` has the property itself, or inherited it
        if (v.hasOwnProperty(propName)) {
            // `v` has the property itself
    
            // If looping an array or array-like thing and you want to see
            // only the *elements* (properties with numeric indexes) and
            // skip any non-element properties:
            if (String(parseInt(propName, 10)) === propName) {
                // It's an array element
            }
        }
    }
    
Sign up to request clarification or add additional context in comments.

3 Comments

@Raynos: Did I have a typo in that first version? Never mind, I changed it anyway, but thanks.
This would certainly get +1 from me if I didn't hit the vote cap - see you in 15 hours :)
Isn't it d.hasOwnProperty(i) in your first snippet (d instead of v) ?
1

I assume, if you use $.each on an array, it uses a normal for loop to iterate over it

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

and a lot of indices in your array are undefined.

for...in instead only loops over the properties of the object which are present. But you should never loop over an array with for...in.

Maybe using an object instead of an array is better in your case.

var d = {}; // <-- object

d[3] = 'qwe';
d[10] = '213';

9 Comments

+1 for you should never loop over an array with for...in.
@FelixKling is it that bad to use an array as a hash when all your keys are numerical?
Yes, but I can't use length method for object. I must write additional function to count objects elements.
@Andrey d.length returns 11 in that example. That's probably not what you wanted anyway.
@Raynos: I would say one should use the right data structure for the right situation. An array should be used if you have a collection of elements that just have to be indexed. But as soon as I don't want/have continuous keys, I would use an object.
|
1

$.each() is iterating over the Array as an Array (probably via a for). When you place a member in an array, everything that is less than upper bound that is not defined becomes undefined.

When you use for ( in ), you are iterating over the enumerable properties of an object. In this case, it is only the properties you set.

If you simply want to subscript Array members, use a for loop.

If you want properties (unordered) from an Object, use for ( in ).

Comments

0

you should trying to except undefined strings with something like that

if (v != "undefined")
{
   console.log(v)
}

2 Comments

... it's v !== undefined or typeof v !== "undefined"
Yes, of course, but very uncomfortable write this in each loop.
0
for (; i < length;) {
    if (callback.apply(object[i++], args) === false) {
        break;
    }
}

From the jQuery source. It iterates over every keyed element if it's not an object. So it handles arrays seperately.

This means it catches all elements between 0 and array.length. If you don't want this behaviour then don't use jQuery.each.

Of course if your using ES5 you can just call .forEach on your array ~

d.forEach(function(val, key) {
   // stuff
});

This will only handle two entries.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.