How does jQuery.each() work with associative array

2019-03-25 11:22发布

I have an associative array with two object inside. Running this through $(myassoc).each(), the callback runs only once. Also the callback parameters (index and object) returns 0 and the entire associative array, respectively.

One would expect jQuery.each() to run for each element in the array, returning the correct keys as index and the correct element as the object.

Why isn't that happening, and can jQuery do what I'm after?

4条回答
爱情/是我丢掉的垃圾
2楼-- · 2019-03-25 11:57

The problem is that the $.each() function internally retrieves and uses the length property of the passed collection. But in an associative array that has no integer indices the length always seems to be 0. For $.each() now there seems to be nothing to walk through.

The $.each() function internally retrieves and uses the length property of the passed collection.

The solutions is simply to use an object instead.

var obj = {
  "flammable": "inflammable",
  "duh": "no duh"
};
$.each( obj, function( key, value ) {
  alert( key + ": " + value );
});
查看更多
手持菜刀,她持情操
3楼-- · 2019-03-25 12:04

Badly.

Don't $(associative_array).each(function () {...}) -- that's nonsense

Don't $.each(associative_array, function() {...}); -- that has an obscure bug(1)

To see the bug, try this in a javascript console:

> $.each({foo:1, length:-1, bar:2}, console.log)
  foo 1
  length -1
  bar 2
> $.each({foo:1, length:0, bar:2}, console.log)

The first example outputs three lines of key-value pairs, as it should. The second outputs nothing!

The moral of the story, don't use jQuery.each() on objects. (Objects in JavaScript are essentially the same thing as associative arrays.) Things may work fine forever, but you run the risk that someday an object happens to have a member named length and its value happens to be exactly 0 and then you have a bug out of nowhere that can be very difficult to explain. (I'll let you guess, by the ponderous heft of this answer, whether that ever happened to me.)

As mentioned in the bug report:

If you need to iterate over all keys of objects having the length property, jQuery.each is not the correct solution.

I suggest going further, that jQuery.each should not be relied upon for associative arrays, ever.

(1) This "bug" may never be fixed, since $.each() historically uses Duck Typing on arrays: "Arrays and array-like objects with a length property (such as a function's arguments object) are iterated by numeric index."


Here's what I use[thanks Dominik] to loop through property names and values of objects, or put another way, the keys and values of an associative array:

function looper(object, callback) {
    for (var key in object) {
        if (object.hasOwnProperty(key)) {
            if (false === callback.call(object[key], key, object[key])) {
                break;
            }
        }
    }
    return object;
}

looper() is then a drop-in replacement for $.each()

> looper({foo:1, length:0, bar:2}, console.log)
  foo 1
  length 0
  bar 2

Just like $.each():

  • Inside the callback, this is each value
  • Inside the callback, returning false (not just falsy) terminates the loop
  • looper() returns the object originally passed to it
  • looper() works on arrays as well as objects.

Use:

var a = [];
looper({foo:1, length:0, bar:2}, function(k, v) { 
    a.push(k+"="+v); 
});
console.assert("foo=1,length=0,bar=2" === a.join());

Try that with $.each() and you'll get an empty result. Because it interprets this particular object as an array-like object of zero length.

查看更多
迷人小祖宗
4楼-- · 2019-03-25 12:14

try this:

$.each(assocarray,function(i, value){
  console.log('index: ' + i + ',value: ' + value);
});
查看更多
相关推荐>>
5楼-- · 2019-03-25 12:16

I think you're looking for jQuery.each() instead of .each()

try this:

    $.each(myassoc, function(index, value){
      //your code
    });
查看更多
登录 后发表回答