Bug Tracker

Ticket #13021 (closed feature: fixed)

Opened 3 years ago

Last modified 9 days ago

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:
Blocking: Blocked by:

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!

Change History

comment:1 Changed 3 years ago by ZengWq572

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!

Last edited 3 years ago by ZengWq572 (previous) (diff)

comment:2 Changed 3 years ago by gibson042

  • Status changed from new to assigned
  • Component changed from unfiled to core
  • Priority changed from undecided to low
  • Milestone changed from None to 1.9
  • Owner set to gibson042
  • Type changed from bug to feature

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

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

comment:3 Changed 3 years ago by Rick Waldron

  • Status changed from assigned to closed
  • Resolution set to fixed

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

Changeset: 07a7b3e4cf961e51bddcdb90cdca34f9126ed286

comment:4 follow-up: ↓ 5 Changed 20 months ago by 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

comment:5 in reply to: ↑ 4 Changed 20 months ago by ZengWq572

Replying to 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@…. and i would like to do my best to help you. any way, thanks for your attention!

comment:6 Changed 9 days ago by ZengWq572

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)
    // `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;
}

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"?

Last edited 9 days ago by ZengWq572 (previous) (diff)
Note: See TracTickets for help on using tickets.