Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does iterating over jQuery objects with .each() not give me jQuery objects?

Tags:

jquery

The following works as expected:

$(".foo").first().text("hi!")

...because first() returns a jQuery object.

However, if I want to work with the text() method for all matches, I need to do:

$(".foo").each( function(idx, obj) {
  $(obj).text("hi!")
  }
)

...because each() gives you DOM objects.

What is the design reason behind this baffling difference? How can I avoid having to build a jQuery object for each match?

like image 357
badp Avatar asked Oct 16 '10 15:10

badp


People also ask

How do you iterate through an object in jQuery?

The $. each() function can be used to iterate over any collection, whether it is an object or an array. In the case of an array, the callback is passed an array index and a corresponding array value each time.

What is .each in jQuery?

The each() method in jQuery specifies a function that runs for every matched element. It is one of the widely used traversing methods in JQuery. Using this method, we can iterate over the DOM elements of the jQuery object and can execute a function for every matched element.

How do I traverse an array in jQuery?

Answer: Use the jQuery. each() function each() or $. each() can be used to seamlessly iterate over any collection, whether it is an object or an array. However, since the $. each() function internally retrieves and uses the length property of the passed array or object.

What is jQuery object?

A jQuery object is array-like which means that it contains zero or more indexes (properties which names are positive integers starting with zero). Besides those indexes, a jQuery object contains these properties: length. context. selector.


2 Answers

Possibly due to performance reasons related to looping over large collections? If you only need the DOM objects, then you save cycles. If you need the jQuery object, then you can easily get that.

I typically don't provide the 2nd parameter to each, so I can use $(this).

like image 198
Kaleb Brasee Avatar answered Sep 23 '22 18:09

Kaleb Brasee


Internally jQuery call this for $("sel").each(function(){});

if ( isObj ) {
    for ( name in object ) {
        if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
            break;
        }
    }
}

And the eq is a simple slice:

eq: function( i ) {
    return i === -1 ?
    this.slice( i ) :
    this.slice( i, +i + 1 );
}

So you can create a new each function that instead of object[name] will do a object:eq(i)

$("*").slice(1,2).toSource() == $("*").eq(1).toSource();

So to create your own each:

$.fn.each2 = function(callback)
{
   for ( var i = 0; i < this.length; ++i ) {
      callback.call( this.eq(i), i, this.eq(i) )
   }
};

$("*").each2(function(i, obj) {
    alert(obj); // now obj is a jQuery object
});

It seems that each3 is faster than each2 http://www.jsfiddle.net/m7pKk/2/

$.fn.each2 = function(callback)
{
   for ( var i = 0; i < this.length; ++i ) {
       var jObj = this.eq(i);
      callback.call( jObj, i, jObj )
   }
};

$.fn.each3 = function(callback)
{
   for ( var i = 0; i < this.length; ++i ) {
       var jObj = $(this[i]);
      callback.call( jObj, i, jObj )
   }
};

See this example on jsFiddle with performance measurement.

like image 24
BrunoLM Avatar answered Sep 19 '22 18:09

BrunoLM