jQuery core each function

I am exploring jQuery framework from its first version. When exploring jquery’s code i saw each function twice.

each function here is append to jQuery prototype.

jQuery.fn = jQuery.prototype = {
.......
each: function( fn, args ) {
    return jQuery.each( this, fn, args );
},

Above the function inside each method function returns again Jquery’s each method which is derived from extend method.

return jQuery.each( this, fn, args );

The second function that each method returns is below.

jQuery.extend({

each: function( obj, fn, args ) {
    if ( obj.length == undefined )
        for ( var i in obj )
            fn.apply( obj[i], args || [i, obj[i]] );
    else
        for ( var i = 0; i < obj.length; i++ )
            fn.apply( obj[i], args || [i, obj[i]] );
    return obj;
},

I would like to know what is purpose to return another each method which is derived via jquery.extend method. Can’t we use one each method directly appended jQuery prototype? Thanks all who have attended.

2 Likes

The $.each() method is a utility function to iterate over arbitrary collections, e.g.

$.each(['foo', 'bar', 'baz'], console.log) // 0 'foo', 1 'bar', 2 'baz'

Whereas the $.fn.each() method is used to specifically iterate over jQuery collections, and is called on such a collection itself (and chainable with other methods of the jQuery prototype):

<div>foo</div>
<div>bar</div>
<div>baz</div>
$('div').each(console.log) // 0 <div>foo</div>, 1 <div>bar</div>, 2 <div>baz</div>

So it makes sense to use the existing helper function under the hood.

BTW, there’s no need to bother with the 1st jQuery version – it just contains deprecated methods and a lot of x-browser (read: IE) fallbacks, which are not necessary any more. Except, of course, you are interested in a bit of history. :-)

3 Likes

Is $.each() method added through jquery.extend method directly to the constructor of jquery? Thank you very much for clearer explanations. Can I give any questions around this topic?

How can I mark this question as solved?

You don’t need to. That’s not the practice here at Sitepoint; I’m not even sure the Discourse software used for the forums offers that feature. All you need to do is leave the thread as is and it will auto-lock after 3 months if there are no other comments in the meantime. It will remain as a reference for others and be discoverable with the search feature.

1 Like

thanks

Have you checked the source code?

[quote=“Azer_Qurbanov, post:3, topic:266558, full:true”]
Is $.each() method added through jquery.extend method directly to the constructor of jquery?

The constructor of jQuery is the Function object.
jQuery’s prototype though does directly contain the .each() method.

Maybe it’s worth noting that $ is used both as a factory function for jQuery objects – as in $('div') – as well as a namespace for a number of utility functions such as $.each(). This is possible in JS because functions are actually objects as well, and as such can have arbitrary properties; and $.fn holds the prototype from which jQuery objects are created. The basic idea goes something like

// Factory function for certain objects that
// provide methods for DOM manipulation
var $ = function (sel) {
  var instance = Object.create($.fn)

  instance.els = document.querySelectorAll(sel)

  return instance
}

// The prototype from which such objects
// are created
$.fn = {
  each: function (callback) {
    $.each(this.els, callback)
    return this
  },

  hide: function () {
    return this.each(function (i, el) {
      el.style.display = 'none'
    })
  },

  show: function () {
    return this.each(function (i, el) {
      el.style.display = 'block'
    })
  }
}

// Utility functions that use the above factory
// function as their namespace
$.each = function (collection, callback) {
  var i
  var item

  for (i = 0; i < collection.length; i++) {
    item = collection[i]
    callback.call(item, i, item)
  }

  return collection
}

By exposing the prototype like this, it can be easily extended with “plugins” – but jQuery itself doesn’t need to .extend() it.

2 Likes

Thanks very much. Sorry for late response.

Thank you very much for both attention and help. I will have another questions about jquery core. If you have time i would give it with pleasure at another time.

I checked it. I am confused about this line.

if ( window == this ) {

       // console.log(new jQuery(a, c))
      
        return new jQuery(a, c);
    }

what does it means here. Code says that if this is not window object, the rest of code will be like this.

var m = /^[^<]*(<.+>)[^>]*$/.exec(a);
    if ( m ) a = jQuery.clean( [ m[1] ] );

    // Watch for when an array is passed in
    this.get( a.constructor == Array || a.length && !a.nodeType && a[0] != undefined && a[0].nodeType ?
        // Assume that it is an array of DOM Elements
        jQuery.merge( a, [] ) :

        // Find the matching elements and save them for later
        jQuery.find( a, c ) );

    // See if an extra function was provided
    var fn = arguments[ arguments.length - 1 ];

    // If so, execute it in context
    if ( fn && fn.constructor == Function )
        this.each(fn);

I dont understand this line.

if ( window == this ) {

       // console.log(new jQuery(a, c))
      
        return new jQuery(a, c);
    }

Thank you for attention.

it prevents the infinite loop you would create when executing new jQuery(a, c).

This is whole code.

function jQuery(a,c) {

    // Shortcut for document ready (because $(document).each() is silly)

    if ( a && a.constructor == Function && jQuery.fn.ready ) {

       // console.log(a)

        return jQuery(document).ready(a);
    }
    else {
      //  console.log(c)

    }

    // Make sure that a selection was provided
    a = a || jQuery.context || document;

    // Watch for when a jQuery object is passed as the selector

    if ( a.jquery ) {

        return $(jQuery.merge(a, []));
    }
    // Watch for when a jQuery object is passed at the context example $( "span", $(this) ).addClass( "bar" );
    if ( c && c.jquery )
        return $( c ).find(a);

    // If the context is global, return a new object
    console.log(this)
    if ( window == this ) {

       // console.log(new jQuery(a, c))
        alert('iki')
        return new jQuery(a, c);
    }

    // Handle HTML strings
    var m = /^[^<]*(<.+>)[^>]*$/.exec(a);
    if ( m ) a = jQuery.clean( [ m[1] ] );

    // Watch for when an array is passed in
    this.get( a.constructor == Array || a.length && !a.nodeType && a[0] != undefined && a[0].nodeType ?
        // Assume that it is an array of DOM Elements
        jQuery.merge( a, [] ) :

        // Find the matching elements and save them for later
        jQuery.find( a, c ) );

    // See if an extra function was provided
    var fn = arguments[ arguments.length - 1 ];

    // If so, execute it in context
    if ( fn && fn.constructor == Function )
        this.each(fn);
//alert('smth')
}

if i delete these lines

if ( window == this ) {

       // console.log(new jQuery(a, c))
      
        return new jQuery(a, c);
    }

at what lines is infinite loop recurring?

as mentioned in the previous post, at the line return new jQuery(a, c); since both $(...) and new jQuery() call the same function (only with different context).

… you would never get a jQuery object.

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.