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 <[email protected]>. 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 [email protected]. 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"?