Skip to main content

Bug Tracker

Side navigation

#13021 closed feature (fixed)

Opened December 09, 2012 07:25AM UTC

Closed December 10, 2012 06:52PM UTC

Last modified June 24, 2015 05:42AM UTC

each() cannot work well with a literal object who has a length member

Reported by: ZengWq572 Owned by: gibson042
Priority: low Milestone: 1.9
Component: core Version: 1.8.3
Keywords: Cc:
Blocked by: Blocking:
Description

if i have a literal object:

var objWithLength =[[BR]]
    length: 2,[[BR]]
    a: 1[[BR]]
};
jQuery.each(objWithLength, function(key, value){[[BR]]
    alert(key + ', ' + value);[[BR]]
});[[BR]]

the each() function cannot work as what i want.

i read the source of jQuery, the each(obj, ...) function only checks 'obj.length' attribute and isFunction(obj). Do you do this for purpose?

if i have the honor, i hope you can sent me an reply.

thank you!

Attachments (0)
Change History (6)

Changed December 09, 2012 07:37AM UTC by ZengWq572 comment:1

_comment0: if i have a literal object with length attribute, the each() function cannot work well as what i want. For example: [[BR]] \ \ {{{ \ var objWithLength = \ length: 2, \ a: 1 \ }; \ jQuery.each(objWithLength, function(key, value){ \ alert(key + ': ' + value); \ }); \ }}} \ \ the each() function will alert out !''1: undefined!'' and !''2: undefined!''. \ [[BR]][[BR]] \ i read the source of jQuery, the each(obj, ...) function only checks 'obj.length' attribute and isFunction(obj). Do you do this for purpose? \ [[BR]][[BR]] \ if i have the honor, i hope you can sent me an reply. \ [[BR]][[BR]] \ thank you!1355039562026646

if i have a literal object with length attribute, the each() function cannot work well as what i want. For example:

var objWithLength = {
    length: 2,
    a: 1
};
jQuery.each(objWithLength, function(key, value){
    alert(key + ': ' + value);
});

the each() function will alert out !''1: undefined!'' and !''2: undefined!''.

i read the source of jQuery, the each(obj, ...) function only checks 'obj.length' attribute and isFunction(obj). Do you do this for purpose?

if i have the honor, i hope you can sent me an reply.

thank you!

Changed December 10, 2012 01:40AM UTC by gibson042 comment:2

component: unfiledcore
milestone: None1.9
owner: → gibson042
priority: undecidedlow
status: newassigned
type: bugfeature

This may get marked wontfix, but there is still a ''little'' bit of wiggle room here.

https://github.com/jquery/jquery/pull/1064

Changed December 10, 2012 06:52PM UTC by Rick Waldron comment:3

resolution: → fixed
status: assignedclosed

Fixes #13021. Normalization of core utility array like detection based on standard protocol by Richard Gibson <richard.gibson@gmail.com>. Closes gh-1064

Changeset: 07a7b3e4cf961e51bddcdb90cdca34f9126ed286

Changed November 19, 2013 07:51AM UTC by anonymous comment:4

$.each($("ul#prod_nav li"), function (key, data) {

console.log(key)

})

Not working, please help me with correct code for latest Jquery 2.x

Changed November 21, 2013 05:51AM UTC by ZengWq572 comment:5

Replying to [comment:4 anonymous]:

$.each($("ul#prod_nav li"), function (key, data) { console.log(key) }) Not working, please help me with correct code for latest Jquery 2.x

May be you have something wrong in you code. i had tried this similarly by my own, and it worked well. if you still cannot checkout the problem, you can send your code to me with email zengweiqun@yeah.net. and i would like to do my best to help you. any way, thanks for your attention!

Changed June 24, 2015 05:42AM UTC by ZengWq572 comment:6

_comment0: This bug is not exactly fixed. There are still some cases that makes each function do not work well. For example:[[BR]] \ \ {{{ \ // If the object.length == 0 \ var objWithLength = { \ length: 0, \ a: 1 \ }; \ // use each on objWithLength \ $.each(objWithLength, function(key, value){ \ console.log(value); \ }) \ }}}[[BR]] \ \ There is nothing to be console.log(ged) out.[[BR]] \ \ Another example:[[BR]] \ \ {{{ \ // If the object.length != 0 \ var objWithLength = { \ length: 2, \ "1": 1, \ "2": 2 \ }; \ // use each on objWithLength \ $.each(objWithLength, function(key, value){ \ console.log(value); \ }) \ }}}[[BR]] \ \ There are something logged out. But the result is not what I want. Under jQuery 1.11.2 version, the logged result is:[[BR]] \ \ {{{ \ undefined \ 1 \ }}}[[BR]] \ \ I have check the jQuery source, there is a isArraylike function used to check whether it should use for...in or for to iterate the object:[[BR]] \ \ {{{ \ function isArraylike( obj ) { \ // Support: iOS 8.2 (not reproducible in simulator) \ // `in` check used to prevent JIT error (gh-2145) \ // hasOwn isn't used here due to false negatives \ // regarding Nodelist length in IE \ var length = "length" in obj && obj.length, \ type = jQuery.type( obj ); \ if ( type === "function" || jQuery.isWindow( obj ) ) { \ return false; \ } \ if ( obj.nodeType === 1 && length ) { \ return true; \ } \ return type === "array" || length === 0 || \ typeof length === "number" && length > 0 && ( length - 1 ) in obj; \ } \ }}}[[BR]] \ \ In fact, there is no good method to check whether an object is arraylike or not. My question is:[[BR]] \ \ why check "length === 0" and "typeof length === "number" && length > 0 && ( length - 1 ) in obj"?[[BR]]1435125137147216

This bug is not exactly fixed. There are still some cases that make each function do not work well. For example:

// If the object.length == 0
var objWithLength = {
    length: 0,
    a: 1
};
// use each on objWithLength
$.each(objWithLength, function(key, value){
    console.log(value);
})

There is nothing to be console.log(ged) out.

Another example:

// If the object.length != 0
var objWithLength = {
    length: 2,
    "1": 1,
    "2": 2
};
// use each on objWithLength
$.each(objWithLength, function(key, value){
    console.log(value);
})

There are something logged out. But the result is not what I want. Under jQuery 1.11.2 version, the logged result is:

undefined
1

I have check the jQuery source, there is a isArraylike function used to check whether it should use for...in or for to iterate the object:

function isArraylike( obj ) {
    // Support: iOS 8.2 (not reproducible in simulator)
    //  check used to prevent JIT error (gh-2145)
    // hasOwn isn't used here due to false negatives
    // regarding Nodelist length in IE
    var length = "length" in obj && obj.length,
        type = jQuery.type( obj );
    if ( type === "function" || jQuery.isWindow( obj ) ) {
        return false;
    }
    if ( obj.nodeType === 1 && length ) {
        return true;
    }
    return type === "array" || length === 0 ||
        typeof length === "number" && length > 0 && ( length - 1 ) in obj;
}

In fact, there is no good method to check whether an object is arraylike or not. My question is:

why check "length === 0" and "typeof length === "number" && length > 0 && ( length - 1 ) in obj"?