2

Having read

How does jQuery accomplish chaining of commands? and how does jquery chaining work?

I am still left to wonder how something like this is possible in jQuery

var a = $('body')
// a returns [<body></body>], an array.

a.click()
// Seems like this should return an error if a returns an array, not a function.

The linked SO answers have only told me how to do things like

a.b().c()

It's the a() I still don't understand. I understand that chaining works by returning this but then how does it also return an array by itself?

Community
  • 1
  • 1
Adam Grant
  • 12,477
  • 10
  • 58
  • 65
  • 11
    jQuery doesn't return an array. It returns a jQuery object. It just pretends to be an array. It's an "array-like" object. – gen_Eric Aug 12 '14 at 17:46
  • there are a few tricks for "upgrading" an array, either page-wide or on a per-instance basis. – dandavis Aug 12 '14 at 17:47
  • Would you provide an example of this fake array, upgrading of an array as an answer, please? – Adam Grant Aug 12 '14 at 17:50
  • 1
    `var x = {"length": 0, splice: Array.prototype.splice}; console.log(x); // []` x is still an object, but it can appear and act like an array depending on how you use it. – Kevin B Aug 12 '14 at 17:51
  • See http://stackoverflow.com/questions/7261670/what-makes-a-jquery-object-show-up-as-an-array-in-chromes-developer-tools and https://www.inkling.com/read/javascript-definitive-guide-david-flanagan-6th/chapter-7/array-like-objects – gen_Eric Aug 12 '14 at 17:53
  • Basically, if an object has `length` and `splice` properties, then Chrome will show it as an array in the console, even though it's not an array. If you use `console.dir` instead of `console.log`, then you'll see what it really is. – gen_Eric Aug 12 '14 at 17:53
  • Looks like I posted a dupe. Shame on me. Thank you, everyone. – Adam Grant Aug 12 '14 at 17:57
  • Voted to close as a duplicate as the only difference between this question and the linked duplicate is that you (mistakenly) thought jQuery was returning an array. This was addressed by the top comment. – user229044 Aug 12 '14 at 18:02
  • 1
    @ajkochanowicz: google for "subclassing array js", "extending Array.prototype", and "proxy array js". you can bring array methods to a custom Constructor's instances, or bring custom methods to Array.prototype. jQuery wasn't in the position to mod prototype, but individual projects might be. – dandavis Aug 12 '14 at 18:43

1 Answers1

1

Using the jQuery source code viewer site the definition for $ (http://james.padolsey.com/jquery/#v=1.9.1&fn=$) is as follows:

$

function (selector, context) {
    // The jQuery object is actually just the init constructor 'enhanced'
    return new jQuery.fn.init(selector, context, rootjQuery);
}

Notice it is returning from init(). Inside of init (http://james.padolsey.com/jquery/#v=1.9.1&fn=init) we see that at the end it calls a function called makeArray:

init

function (selector, context, rootjQuery) {
    var match, elem;

// rest of function defintion

    return jQuery.makeArray(selector, this);
}

Which brings us to the answer to the question 'How does jQuery chain functions while still returning an array?'

makeArray (http://james.padolsey.com/jquery/#v=1.9.1&fn=jQuery.makeArray) looks like this:

makeArray

function (arr, results) {
    var ret = results || [];

    if (arr != null) {
        if (isArraylike(Object(arr))) {
            jQuery.merge(ret, typeof arr === "string" ? [arr] : arr);
        } else {
            core_push.call(ret, arr);
        }
    }

    return ret;
}
BenMorel
  • 34,448
  • 50
  • 182
  • 322
Mike Cheel
  • 12,626
  • 10
  • 72
  • 101
  • 1
    I've been pouring over the jQuery code and couldn't make sense of the path it takes until now. Thank you. – Adam Grant Aug 12 '14 at 18:02