Skip to main content

Bug Tracker

Side navigation

#7260 closed bug (invalid)

Opened October 20, 2010 08:02PM UTC

Closed October 20, 2010 09:32PM UTC

Last modified July 24, 2012 01:09AM UTC

$.each() fails on an object when the object has a key named 'length'

Reported by: lucas.madar@gmail.com Owned by:
Priority: undecided Milestone: 1.5
Component: unfiled Version: 1.4.2
Keywords: Cc:
Blocked by: Blocking:
Description

If you have an object, like this:

var obj = { name: "something", length: 12, height: 32 };

and then you try to iterate over it using $.each:

$.each( obj, function( key, value ) {
    ...
} );

The inner function is never called because jquery treats the object as an array instead of an object. This behavior is unexpected; it should either be documented or fixed.

Attachments (0)
Change History (9)

Changed October 20, 2010 09:23PM UTC by jitter comment:1

_comment0: I think you misread the documentation. `$.each` behaves exactly as expected and as documented. \ \ From http://api.jquery.com/jQuery.each/ \ >Arrays and **array-like objects with a length property** (such as a function's arguments object) are iterated by numeric index, from 0 to length-1. Other objects are iterated via their named properties. \ \ This sentence covers your case, stating that objects with a length property (as in your example) are iterated by numeric index. \ \ So if you remove/name the length property in your sample object `$.each` while behave as expected. \ \ Here a [http://www.jsfiddle.net/jitter/qvWAQ/ live test case] to show what is happening.1287609930874185

This exact behavior is well documented thus $.each behaves exactly as expected.

From http://api.jquery.com/jQuery.each/

>Arrays and **array-like objects with a length property** (such as a function's arguments object) are iterated by numeric index, from 0 to length-1. Other objects are iterated via their named properties.

Here a live test case to show what is happening.

Changed October 20, 2010 09:32PM UTC by snover comment:2

resolution: → invalid
status: newclosed

Changed March 06, 2011 12:17AM UTC by anonymous comment:3

I fail to see how a json object with a quoted length property could be considered an array-like object.

Changed March 31, 2011 02:37PM UTC by anonymous comment:4

This is also a problem in jQuery templates when using {{each}} to iterate through an object which happens to have a "length" key.

Changed April 16, 2011 06:35PM UTC by jboesch comment:5

_comment0: I think we can fix this issue. If jQuery.map is supporting objects in 1.6 (and works with length props) I think we should maybe consider adding it here. \ \ '''Here is what the code is right now:''' \ isObj = length === undefined || jQuery.isFunction( object ); \ \ '''This can be changed to what's being used in jQuery.map (v 1.6):''' \ isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || jQuery.isArray( elems ) ) ; \ \ Here's Dan's isArray var in action in the jQuery.map function: https://github.com/jquery/jquery/pull/299/files \ \ This would allow looping over objects with length props. I'm not sure the speed implications, that would have to be tested. \ 1302979008229212
_comment1: I think we can fix this issue. If jQuery.map is supporting objects in 1.6 (and works with length props) I think we should maybe consider adding it here. \ \ '''Here is what the code is right now being used in jQuery.each (object/array detection):''' \ \ {{{ \ isObj = length === undefined || jQuery.isFunction( object ); \ }}} \ \ \ '''This can be changed to what's being used in jQuery.map (v 1.6):''' \ \ {{{ \ isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || jQuery.isArray( elems ) ) ; \ }}} \ \ \ Here's Dan's isArray var in action in the jQuery.map function: https://github.com/jquery/jquery/pull/299/files \ \ This would allow looping over objects with length props. I'm not sure the speed implications, that would have to be tested. \ 1302979914983617
_comment2: I think we can fix this issue. If jQuery.map is supporting objects in 1.6 (and works with length props) I think we should maybe consider adding it here. \ \ '''Here is what the code is right now being used in jQuery.each (object/array detection):''' \ \ {{{ \ isObj = length === undefined || jQuery.isFunction( object ); \ }}} \ \ \ '''This can be changed to what's being used in jQuery.map (v 1.6):''' \ \ {{{ \ isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || jQuery.isArray( elems ) ) ; \ }}} \ \ \ Here's Dan's isArray var in action in the jQuery.map function: https://github.com/jquery/jquery/pull/299/files \ \ Here's a fiddle with me changing that one line: http://jsfiddle.net/jboesch26/Ungsa/ \ \ This would allow looping over objects with length props. I'm not sure the speed implications, that would have to be tested. \ 1302982098738507
_comment3: I think we can fix this issue. If jQuery.map is supporting objects in 1.6 (and works with length props) I think we should maybe consider adding it here. \ \ '''Here is what the code is right now being used in jQuery.each (object/array detection):''' \ \ {{{ \ isObj = length === undefined || jQuery.isFunction( object ); \ }}} \ \ \ '''This can be changed to what's being used in jQuery.map (v 1.6):''' \ \ {{{ \ isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || jQuery.isArray( elems ) ) ; \ }}} \ \ \ Here's Dan's isArray var in action in the jQuery.map function: https://github.com/jquery/jquery/pull/299/files \ \ Here's a fiddle with me changing that one line: http://jsfiddle.net/jboesch26/Ungsa/ \ \ This would allow looping over objects with length props. This newEach proposal seems to be slightly faster as well: http://jsperf.com/each-object-supporting-length-key \ 1302982139150960
_comment4: I think we can fix this issue. If jQuery.map is supporting objects in 1.6 (and works with length props) I think we should maybe consider adding it here. \ \ '''Here is what the code is right now being used in jQuery.each (object/array detection):''' \ \ {{{ \ isObj = length === undefined || jQuery.isFunction( object ); \ }}} \ \ \ '''This can be changed to what's being used in jQuery.map (v 1.6):''' \ \ {{{ \ isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || jQuery.isArray( elems ) ) ; \ }}} \ \ \ Here's Dan's isArray var in action in the jQuery.map function: https://github.com/jquery/jquery/pull/299/files \ \ Here's a fiddle with me changing that one line: http://jsfiddle.net/jboesch26/Ungsa/ \ \ This would allow looping over objects with length props. This newEach proposal seems to be slightly faster as well: http://jsperf.com/each-object-supporting-length-key \ \ If this is cool, I'll make a pull request. \ 1303088355745872
_comment5: I think we can fix this issue. If jQuery.map is supporting objects in 1.6 (and works with length props) I think we should maybe consider adding it here. \ \ '''Here is what the code is right now being used in jQuery.each (object/array detection):''' \ \ {{{ \ isObj = length === undefined || jQuery.isFunction( object ); \ }}} \ \ \ '''This can be changed to what's being used in jQuery.map (v 1.6):''' \ \ {{{ \ isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || jQuery.isArray( elems ) ) ; \ }}} \ \ \ Here's Dan's isArray var in action in the jQuery.map function: https://github.com/jquery/jquery/pull/299/files \ \ Here's a fiddle with me changing that one line: http://jsfiddle.net/jboesch26/Ungsa/ \ \ This would allow looping over objects with length props. This newEach proposal seems to be slightly faster as well: http://jsperf.com/each-object-supporting-length-key/4 \ \ If this is cool, I'll make a pull request. \ 1303155014015869
_comment6: I think we can fix this issue. If jQuery.map is supporting objects in 1.6 (and works with length props) I think we should maybe consider adding it here. \ \ '''Here is what the code is right now being used in jQuery.each (object/array detection):''' \ \ {{{ \ isObj = length === undefined || jQuery.isFunction( object ); \ }}} \ \ \ '''This can be changed to what's being used in jQuery.map (v 1.6):''' \ \ {{{ \ isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || jQuery.isArray( elems ) ) ; \ }}} \ \ \ Here's Dan's isArray var in action in the jQuery.map function: https://github.com/jquery/jquery/pull/299/files \ \ Here's a fiddle with me changing that one line: http://jsfiddle.net/jboesch26/Ungsa/ \ \ This would allow looping over objects with length props. This newEach proposal seems to be slightly faster as well: http://jsperf.com/each-object-supporting-length-key/6 \ \ If this is cool, I'll make a pull request. \ 1303155026828096

I think we can fix this issue. If jQuery.map is supporting objects in 1.6 (and works with length props) I think we should maybe consider adding it here.

Here is what the code is right now being used in jQuery.each (object/array detection):

isObj = length === undefined || jQuery.isFunction( object );

'''This can be changed to what's being used in jQuery.map (v 1.6):'''

isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || jQuery.isArray( elems ) ) ;

Here's Dan's isArray var in action in the jQuery.map function: https://github.com/jquery/jquery/pull/299/files

Here's a fiddle with me changing that one line: http://jsfiddle.net/jboesch26/Ungsa/

This would allow looping over objects with length props. This newEach2 proposal seems to be slightly faster as well: http://jsperf.com/each-object-supporting-length-key/6

If this is cool, I'll make a pull request.

Changed April 18, 2011 05:20AM UTC by jboesch comment:6

_comment0: I've committed a patch, but I'm gonna finish testing in IE before making a pull request: \ https://github.com/jboesch/jquery/commit/507e48c040cd5aaf70a50d402d5f91fc07f0ea7b1303182363336430
_comment1: Pull requested: https://github.com/jquery/jquery/pull/336/files1303182373397782

Changed April 10, 2012 10:22AM UTC by sindresorhus comment:7

#11573 is a duplicate of this ticket.

Changed May 24, 2012 03:18PM UTC by dmethvin comment:8

#11810 is a duplicate of this ticket.

Changed July 24, 2012 01:09AM UTC by dmethvin comment:9

#12130 is a duplicate of this ticket.