Skip to main content

Bug Tracker

Side navigation

#2827 closed enhancement (fixed)

Opened May 08, 2008 06:57PM UTC

Closed June 20, 2009 03:52PM UTC

Last modified October 28, 2010 04:15AM UTC

$.each Treats Functions as Arrays

Reported by: dschoon Owned by: flesler
Priority: minor Milestone: 1.4
Component: core Version: 1.3.2
Keywords: Cc: dschoon
Blocked by: Blocking:
Description

Calling $.each on a function will result in it iterating over [0..arity], not the properties of the function object.

This is because $.each checks whether obj.length is defined, rather than checking whether the object is an array. In the case of a function object, Function.length will be defined, and it will be the arity of the function. This also screws user-defined types which have a length property.

Boo!

Attachments (2)
Change History (10)

Changed May 08, 2008 07:07PM UTC by dschoon comment:1

Patch attached. I guess I should have checked whether I have check-in privileges by default, but I assume not.

Changed May 08, 2008 08:28PM UTC by flesler comment:2

resolution: → wontfix
status: newclosed

I can tell you in advance, what a core developer will say: this function is internal, is the most used function all over the framework, so if this behavior (iterating functions) is not required by the core, then it won't be changed.

Also, this patch doesn't support any array-like (arguments, nodelist, jQuery object, etc).

>I guess I should have checked whether I have check-in privileges by default, but I assume not.

There's no permissions system integrated into the SVN. But only those allowed can "legally" commit.

Changed May 08, 2008 11:36PM UTC by dschoon comment:3

Internal? Really? http://docs.jquery.com/Core/each#callback

I mean, if it's in the docs, it seems pretty public to me.

Changed May 08, 2008 11:37PM UTC by dschoon comment:4

Also, legit criticism for array-like objects; I guess the only technically correct solution would be to special-case for Functions.

Changed May 21, 2008 05:57PM UTC by flesler comment:5

You're confusing $.each and $().each.

$.each is a generic iterator, it receives 2 arguments: collection and callback

$().each ($.fn.each) is a special use of $.each, it iterates over the elements of a jQuery collection. It only receives the callback, and the calling collection is used.

The function mentioned in the docs, refers to the callback. Functions aren't supported.

Changed June 17, 2009 10:44PM UTC by micah comment:6

resolution: wontfix
status: closedreopened

Reopening this, as it still exists and IMO is indeed a valid bug.

In http://dev.jquery.com/browser/tags/1.3.2/src/core.js#L662 $.each checks for length === undefined, which breaks in this use case:

var someFunction = function(){};
$.each(someFunction, function(key){
    alert(key);
});

The docs say "Other objects are iterated via their named properties.", so you'd expect that code to iterate over the built-in properties and methods of that instance of Function, but instead it tries to loop through properties named [0...arity], which don't exist.

The fix is pretty painless. Change the two offending lines from:

if ( length === undefined ) {

to:

if ( length === undefined || object.constructor == Function ) {

...et voila, $.each should hit the for...in condition that works on functions.

I only added the specific exception for Function because I can't think of anything else off the top of my head that allows for...in but doesn't currently work with $.each.

Changed June 20, 2009 03:52PM UTC by flesler comment:7

cc: → dschoon
milestone: 1.2.41.3.3
owner: → flesler
status: reopenednew
type: bugenhancement
version: 1.2.31.3.2

Changed June 20, 2009 03:52PM UTC by flesler comment:8

status: newassigned

Changed June 20, 2009 03:52PM UTC by flesler comment:9

resolution: → fixed
status: assignedclosed

Fixed at [6410].

Changed October 28, 2010 04:15AM UTC by addyosmani comment:10

#5002 is a duplicate of this ticket.